Beispiel #1
0
    def _load_favorites(self):
        for i in range(desktop.get_number_of_views()):
            # Special-case 0 for backward compatibility
            if i == 0:
                favorites_path = env.get_profile_path('favorite_activities')
            else:
                favorites_path = env.get_profile_path(
                    'favorite_activities_%d' % (i))
            if os.path.exists(favorites_path):
                favorites_data = json.load(open(favorites_path))

                favorite_bundles = favorites_data['favorites']
                if not isinstance(favorite_bundles, dict):
                    raise ValueError('Invalid format in %s.' % favorites_path)
                if favorite_bundles:
                    first_key = favorite_bundles.keys()[0]
                    if not isinstance(first_key, basestring):
                        raise ValueError('Invalid format in %s.' %
                                         favorites_path)

                    first_value = favorite_bundles.values()[0]
                    if first_value is not None and \
                       not isinstance(first_value, dict):
                        raise ValueError('Invalid format in %s.' %
                                         favorites_path)

                self._last_defaults_mtime[i] = \
                    float(favorites_data['defaults-mtime'])
                self._favorite_bundles[i] = favorite_bundles
Beispiel #2
0
    def _load_favorites(self):
        for i in range(desktop.get_number_of_views()):
            # Special-case 0 for backward compatibility
            if i == 0:
                favorites_path = env.get_profile_path('favorite_activities')
            else:
                favorites_path = env.get_profile_path(
                    'favorite_activities_%d' % (i))
            if os.path.exists(favorites_path):
                favorites_data = json.load(open(favorites_path))

                favorite_bundles = favorites_data['favorites']
                if not isinstance(favorite_bundles, dict):
                    raise ValueError('Invalid format in %s.' % favorites_path)
                if favorite_bundles:
                    first_key = favorite_bundles.keys()[0]
                    if not isinstance(first_key, basestring):
                        raise ValueError('Invalid format in %s.' %
                                         favorites_path)

                    first_value = favorite_bundles.values()[0]
                    if first_value is not None and \
                       not isinstance(first_value, dict):
                        raise ValueError('Invalid format in %s.' %
                                         favorites_path)

                self._favorite_bundles[i] = favorite_bundles
Beispiel #3
0
def _setup_env(display, scaling, emulator_pid):
    # We need to remove the environment related to gnome-keyring-daemon,
    # so a new instance of gnome-keyring-daemon can be started and
    # registered properly.
    for variable in ['GPG_AGENT_INFO', 'SSH_AUTH_SOCK',
                     'GNOME_KEYRING_CONTROL', 'GNOME_KEYRING_PID']:
        if variable in os.environ:
            del os.environ[variable]

    os.environ['SUGAR_EMULATOR'] = 'yes'
    os.environ['GABBLE_LOGFILE'] = os.path.join(
            env.get_profile_path(), 'logs', 'telepathy-gabble.log')
    os.environ['SALUT_LOGFILE'] = os.path.join(
            env.get_profile_path(), 'logs', 'telepathy-salut.log')
    os.environ['MC_LOGFILE'] = os.path.join(
            env.get_profile_path(), 'logs', 'mission-control.log')
    os.environ['STREAM_ENGINE_LOGFILE'] = os.path.join(
            env.get_profile_path(), 'logs', 'telepathy-stream-engine.log')
    os.environ['DISPLAY'] = ':%d' % (display)
    os.environ['SUGAR_EMULATOR_PID'] = emulator_pid
    os.environ['MC_ACCOUNT_DIR'] = os.path.join(
            env.get_profile_path(), 'accounts')

    if scaling:
        os.environ['SUGAR_SCALING'] = scaling
Beispiel #4
0
 def _write_favorites_file(self, favorite_view):
     if favorite_view == 0:
         path = env.get_profile_path('favorite_activities')
     else:
         path = env.get_profile_path('favorite_activities_%d' %
                                     (favorite_view))
     favorites_data = {'favorites': self._favorite_bundles[favorite_view]}
     json.dump(favorites_data, open(path, 'w'), indent=1)
Beispiel #5
0
 def _write_favorites_file(self, favorite_view):
     if favorite_view == 0:
         path = env.get_profile_path('favorite_activities')
     else:
         path = env.get_profile_path('favorite_activities_%d' %
                                     (favorite_view))
     favorites_data = {
         'favorites': self._favorite_bundles[favorite_view]}
     json.dump(favorites_data, open(path, 'w'), indent=1)
Beispiel #6
0
 def _write_favorites_file(self, favorite_view):
     if favorite_view == 0:
         path = env.get_profile_path("favorite_activities")
     else:
         path = env.get_profile_path("favorite_activities_%d" % (favorite_view))
     favorites_data = {
         "defaults-mtime": self._last_defaults_mtime[favorite_view],
         "favorites": self._favorite_bundles[favorite_view],
     }
     json.dump(favorites_data, open(path, "w"), indent=1)
Beispiel #7
0
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        self._autosearch_timer = None

        # Paths to watch: ~/.sugar/someuser/logs, /var/log
        paths = []
        paths.append(env.get_profile_path('logs'))
        paths.append('/var/log')

        # Additional misc files.
        ext_files = []
        ext_files.append(os.path.expanduser('~/.bash_history'))

        self.viewer = MultiLogView(paths, ext_files)
        self.set_canvas(self.viewer)
        self.viewer.grab_focus()

        self._build_toolbox()

        # Get Sugar's clipboard
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.show()

        self._configure_cb(None)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)
def _store_identifiers(serial_number, uuid_, backup_url):
    """  Stores the serial number, uuid and backup_url
    in the identifier folder inside the profile directory
    so that these identifiers can be used for backup. """

    identifier_path = os.path.join(env.get_profile_path(), 'identifiers')
    if not os.path.exists(identifier_path):
        os.mkdir(identifier_path)

    if os.path.exists(os.path.join(identifier_path, 'sn')):
        os.remove(os.path.join(identifier_path, 'sn'))
    serial_file = open(os.path.join(identifier_path, 'sn'), 'w')
    serial_file.write(serial_number)
    serial_file.close()

    if os.path.exists(os.path.join(identifier_path, 'uuid')):
        os.remove(os.path.join(identifier_path, 'uuid'))
    uuid_file = open(os.path.join(identifier_path, 'uuid'), 'w')
    uuid_file.write(uuid_)
    uuid_file.close()

    if os.path.exists(os.path.join(identifier_path, 'backup_url')):
        os.remove(os.path.join(identifier_path, 'backup_url'))
    backup_url_file = open(os.path.join(identifier_path, 'backup_url'), 'w')
    backup_url_file.write(backup_url)
    backup_url_file.close()
    def _hash_private_key(self):
        key_path = os.path.join(env.get_profile_path(), 'owner.key')

        if not os.path.exists(key_path):
            return None

        try:
            f = open(key_path, 'r')
            lines = f.readlines()
            f.close()
        except IOError:
            logging.exception('Error reading private key')
            return None

        key = ""
        begin_found = False
        end_found = False
        for l in lines:
            l = l.strip()
            if l.startswith('-----BEGIN DSA PRIVATE KEY-----'):
                begin_found = True
                continue
            if l.startswith('-----END DSA PRIVATE KEY-----'):
                end_found = True
                continue
            key += l
        if not (len(key) and begin_found and end_found):
            logging.error('Error parsing public key.')
            return None

        # hash it
        key_hash = util.sha_data(key)
        return util.printable_hash(key_hash)
def get_environment(activity):
    environ = os.environ.copy()

    bin_path = os.path.join(activity.get_path(), 'bin')

    activity_root = env.get_profile_path(activity.get_bundle_id())
    _mkdir(activity_root)

    instance_dir = os.path.join(activity_root, 'instance')
    _mkdir(instance_dir)

    data_dir = os.path.join(activity_root, 'data')
    _mkdir(data_dir)

    tmp_dir = os.path.join(activity_root, 'tmp')
    _mkdir(tmp_dir)

    environ['SUGAR_BUNDLE_PATH'] = activity.get_path()
    environ['SUGAR_BUNDLE_ID'] = activity.get_bundle_id()
    environ['SUGAR_ACTIVITY_ROOT'] = activity_root
    environ['PATH'] = bin_path + ':' + environ['PATH']

    if activity.get_path().startswith(env.get_user_activities_path()):
        environ['SUGAR_LOCALEDIR'] = os.path.join(activity.get_path(),
                                                  'locale')

    return environ
Beispiel #11
0
    def __init__(self):
        GObject.GObject.__init__(self)

        self._friends = {}
        self._path = os.path.join(env.get_profile_path(), 'friends')

        self.load()
Beispiel #12
0
    def __init__(self, handle):
        activity.Activity.__init__(self, handle)

        self._autosearch_timer = None

        # Paths to watch: ~/.sugar/someuser/logs, /var/log
        paths = []
        paths.append(env.get_profile_path('logs'))
        paths.append('/var/log')

        # Additional misc files.
        ext_files = []
        ext_files.append(os.path.expanduser('~/.bash_history'))

        self.viewer = MultiLogView(paths, ext_files)
        self.set_canvas(self.viewer)
        self.viewer.grab_focus()

        self._build_toolbox()

        # Get Sugar's clipboard
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        self.show()

        self._configure_cb(None)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)
Beispiel #13
0
def create_profile(name, color=None):
    if not color:
        color = XoColor()

    client = GConf.Client.get_default()
    client.set_string('/desktop/sugar/user/nick', name)
    client.set_string('/desktop/sugar/user/color', color.to_string())
    client.suggest_sync()

    if profile.get_pubkey() and profile.get_profile().privkey_hash:
        logging.info('Valid key pair found, skipping generation.')
        return

    # Generate keypair
    import commands
    keypath = os.path.join(env.get_profile_path(), 'owner.key')
    if os.path.exists(keypath):
        os.rename(keypath, keypath + '.broken')
        logging.warning('Existing private key %s moved to %s.broken',
                        keypath, keypath)

    if os.path.exists(keypath + '.pub'):
        os.rename(keypath + '.pub', keypath + '.pub.broken')
        logging.warning('Existing public key %s.pub moved to %s.pub.broken',
                        keypath, keypath)

    logging.debug("Generating user keypair")

    cmd = "ssh-keygen -q -t dsa -f %s -C '' -N ''" % (keypath, )
    (s, o) = commands.getstatusoutput(cmd)
    if s != 0:
        logging.error('Could not generate key pair: %d %s', s, o)

    logging.debug("User keypair generated")
Beispiel #14
0
    def __init__(self):
        GObject.GObject.__init__(self)

        self._friends = {}
        self._path = os.path.join(env.get_profile_path(), 'friends')

        self.load()
Beispiel #15
0
    def __init__(self, activity, window_xid):
        self.parent_window_xid = window_xid

        url, title = get_help_url_and_title(activity)
        has_local_help = url is not None
        self._mode = _MODE_HELP if has_local_help else _MODE_SOCIAL_HELP

        Gtk.Window.__init__(self)
        box = Gtk.Box()
        box.set_orientation(Gtk.Orientation.VERTICAL)
        self.add(box)
        box.show()

        self.set_decorated(False)
        self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
        self.set_border_width(style.LINE_WIDTH)
        self.set_has_resize_grip(False)

        width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2
        height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2
        self.set_size_request(width, height)

        self.connect('realize', self.__realize_cb)
        self.connect('hide', self.__hide_cb)
        self.connect('key-press-event', self.__key_press_event_cb)

        toolbar = Toolbar(title, has_local_help)
        box.pack_start(toolbar, False, False, 0)
        toolbar.show()
        toolbar.connect('stop-clicked', self.__stop_clicked_cb)
        toolbar.connect('mode-changed', self.__mode_changed_cb)

        session = WebKit.get_default_session()
        cookie_jar = SoupGNOME.CookieJarSqlite(
            filename=os.path.join(env.get_profile_path(),
                                  'social-help.cookies'),
            read_only=False)
        session.add_feature(cookie_jar)

        self._webview = WebKit.WebView()
        self._webview.set_full_content_zoom(True)
        self._webview.connect('resource-request-starting',
                              self._resource_request_starting_cb)

        scrolled_window = Gtk.ScrolledWindow()
        scrolled_window.add(self._webview)
        scrolled_window.show()

        box.pack_start(scrolled_window, True, True, 0)
        self._webview.show()

        language = self._get_current_language()
        if has_local_help:
            self._help_url = 'file://' + self._get_help_file(language, url)
        self._social_help_url = '{}/goto/{}'.format(
            get_social_help_server(), activity.get_bundle_id())

        self._webview.connect(
            'notify::load-status', self.__load_status_changed_cb)
        self._load_mode(self._mode)
def get_environment(activity):
    environ = os.environ.copy()

    bin_path = os.path.join(activity.get_path(), 'bin')

    activity_root = env.get_profile_path(activity.get_bundle_id())
    if not os.path.exists(activity_root):
        os.mkdir(activity_root)

    data_dir = os.path.join(activity_root, 'instance')
    if not os.path.exists(data_dir):
        os.mkdir(data_dir)

    data_dir = os.path.join(activity_root, 'data')
    if not os.path.exists(data_dir):
        os.mkdir(data_dir)

    tmp_dir = os.path.join(activity_root, 'tmp')
    if not os.path.exists(tmp_dir):
        os.mkdir(tmp_dir)

    environ['SUGAR_BUNDLE_PATH'] = activity.get_path()
    environ['SUGAR_BUNDLE_ID'] = activity.get_bundle_id()
    environ['SUGAR_ACTIVITY_ROOT'] = activity_root
    environ['PATH'] = bin_path + ':' + environ['PATH']

    if activity.get_path().startswith(env.get_user_activities_path()):
        environ['SUGAR_LOCALEDIR'] = os.path.join(activity.get_path(),
                                                  'locale')

    return environ
Beispiel #17
0
 def _write_favorites_file(self):
     path = env.get_profile_path('favorite_activities')
     favorites_data = {
         'defaults-mtime': self._last_defaults_mtime,
         'favorites': self._favorite_bundles
     }
     json.dump(favorites_data, open(path, 'w'), indent=1)
    def _hash_private_key(self):
        key_path = os.path.join(env.get_profile_path(), 'owner.key')

        if not os.path.exists(key_path):
            return None

        try:
            f = open(key_path, 'r')
            lines = f.readlines()
            f.close()
        except IOError:
            logging.exception('Error reading private key')
            return None

        key = ""
        begin_found = False
        end_found = False
        for line in lines:
            line = line.strip()
            if line.startswith(('-----BEGIN DSA PRIVATE KEY-----',
                                '-----BEGIN OPENSSH PRIVATE KEY-----')):
                begin_found = True
                continue
            if line.startswith(('-----END DSA PRIVATE KEY-----',
                                '-----END OPENSSH PRIVATE KEY-----')):
                end_found = True
                continue
            key += line
        if not (len(key) and begin_found and end_found):
            logging.error('Error parsing public key.')
            return None

        # hash it
        key_hash = util.sha_data(key)
        return util.printable_hash(key_hash)
    def uninstall(self, force=False, delete_profile=False):
        install_path = self.get_path()

        if os.path.islink(install_path):
            # Don't remove the actual activity dir if it's a symbolic link
            # because we may be removing user data.
            os.unlink(install_path)
            return

        xdg_data_home = os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share"))

        mime_dir = os.path.join(xdg_data_home, "mime")
        installed_mime_path = os.path.join(mime_dir, "packages", "%s.xml" % self._bundle_id)
        if os.path.exists(installed_mime_path):
            os.remove(installed_mime_path)
            os.spawnlp(os.P_WAIT, "update-mime-database", "update-mime-database", mime_dir)

        mime_types = self.get_mime_types()
        if mime_types is not None:
            installed_icons_dir = os.path.join(xdg_data_home, "icons/sugar/scalable/mimetypes")
            if os.path.isdir(installed_icons_dir):
                for f in os.listdir(installed_icons_dir):
                    path = os.path.join(installed_icons_dir, f)
                    if os.path.islink(path) and os.readlink(path).startswith(install_path):
                        os.remove(path)

        if delete_profile:
            bundle_profile_path = env.get_profile_path(self._bundle_id)
            if os.path.exists(bundle_profile_path):
                os.chmod(bundle_profile_path, 0775)
                shutil.rmtree(bundle_profile_path, ignore_errors=True)

        self._uninstall(install_path)
Beispiel #20
0
def create_profile(name, color=None):
    if not color:
        color = XoColor()

    client = GConf.Client.get_default()
    client.set_string('/desktop/sugar/user/nick', name)
    client.set_string('/desktop/sugar/user/color', color.to_string())
    client.suggest_sync()

    if profile.get_pubkey() and profile.get_profile().privkey_hash:
        logging.info('Valid key pair found, skipping generation.')
        return

    # Generate keypair
    import commands
    keypath = os.path.join(env.get_profile_path(), 'owner.key')
    if os.path.exists(keypath):
        os.rename(keypath, keypath + '.broken')
        logging.warning('Existing private key %s moved to %s.broken', keypath,
                        keypath)

    if os.path.exists(keypath + '.pub'):
        os.rename(keypath + '.pub', keypath + '.pub.broken')
        logging.warning('Existing public key %s.pub moved to %s.pub.broken',
                        keypath, keypath)

    logging.debug("Generating user keypair")

    cmd = "ssh-keygen -q -t dsa -f %s -C '' -N ''" % (keypath, )
    (s, o) = commands.getstatusoutput(cmd)
    if s != 0:
        logging.error('Could not generate key pair: %d %s', s, o)

    logging.debug("User keypair generated")
Beispiel #21
0
    def __init__(self, activity, window_xid):
        self.parent_window_xid = window_xid

        url, title = get_help_url_and_title(activity)
        has_local_help = url is not None
        self._mode = _MODE_HELP if has_local_help else _MODE_SOCIAL_HELP

        Gtk.Window.__init__(self)
        box = Gtk.Box()
        box.set_orientation(Gtk.Orientation.VERTICAL)
        self.add(box)
        box.show()

        self.set_decorated(False)
        self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
        self.set_border_width(style.LINE_WIDTH)
        self.set_has_resize_grip(False)

        width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2
        height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2
        self.set_size_request(width, height)

        self.connect('realize', self.__realize_cb)
        self.connect('hide', self.__hide_cb)
        self.connect('key-press-event', self.__key_press_event_cb)

        toolbar = Toolbar(title, has_local_help)
        box.pack_start(toolbar, False, False, 0)
        toolbar.show()
        toolbar.connect('stop-clicked', self.__stop_clicked_cb)
        toolbar.connect('mode-changed', self.__mode_changed_cb)

        session = WebKit.get_default_session()
        cookie_jar = SoupGNOME.CookieJarSqlite(filename=os.path.join(
            env.get_profile_path(), 'social-help.cookies'),
                                               read_only=False)
        session.add_feature(cookie_jar)

        self._webview = WebKit.WebView()
        self._webview.set_full_content_zoom(True)
        self._webview.connect('resource-request-starting',
                              self._resource_request_starting_cb)

        scrolled_window = Gtk.ScrolledWindow()
        scrolled_window.add(self._webview)
        scrolled_window.show()

        box.pack_start(scrolled_window, True, True, 0)
        self._webview.show()

        language = self._get_current_language()
        if has_local_help:
            self._help_url = 'file://' + self._get_help_file(language, url)
        self._social_help_url = '{}/goto/{}'.format(get_social_help_server(),
                                                    activity.get_bundle_id())

        self._webview.connect('notify::load-status',
                              self.__load_status_changed_cb)
        self._load_mode(self._mode)
Beispiel #22
0
    def __init__(self, activity, window_xid):
        self.parent_window_xid = window_xid

        url, title = get_help_url_and_title(activity)
        has_local_help = url is not None
        self._mode = _MODE_HELP if has_local_help else _MODE_SOCIAL_HELP

        Gtk.Window.__init__(self)
        box = Gtk.Box()
        box.set_orientation(Gtk.Orientation.VERTICAL)
        self.add(box)
        box.show()

        self.set_modal(True)
        self.set_decorated(False)
        self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
        self.set_border_width(style.LINE_WIDTH)
        self.set_has_resize_grip(False)

        width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2
        height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2
        self.set_size_request(width, height)

        self.connect('realize', self.__realize_cb)
        self.connect('hide', self.__hide_cb)
        self.connect('key-press-event', self.__key_press_event_cb)

        self._toolbar = Toolbar(title, has_local_help)
        box.pack_start(self._toolbar, False, False, 0)
        self._toolbar.show()
        self._toolbar.connect('stop-clicked', self.__stop_clicked_cb)
        self._toolbar.connect('mode-changed', self.__mode_changed_cb)

        context = WebKit2.WebContext.get_default()
        cookie_manager = context.get_cookie_manager()
        cookie_manager.set_persistent_storage(
            os.path.join(env.get_profile_path(), 'social-help.cookies'),
            WebKit2.CookiePersistentStorage.SQLITE)

        self._webview = WebKit2.WebView()
        self._webview.get_context().register_uri_scheme(
            'help', self.__app_scheme_cb, None)
        self._toolbar.bind_webview(self._webview)

        box.pack_start(self._webview, True, True, 0)
        self._webview.show()

        language = self._get_current_language()
        self._help_state = None
        if has_local_help:
            self._help_url = 'help://' + self._get_help_file(language, url)

        self._social_help_uri = '{}/goto/{}'.format(
            get_social_help_server(), activity.get_bundle_id())
        self._social_help_state = None

        self._webview.connect(
            'load-changed', self.__load_changed_cb)
        self._load_mode(self._mode)
Beispiel #23
0
    def _configure_vt(self, vt):
        conf = ConfigParser.ConfigParser()
        conf_file = os.path.join(env.get_profile_path(), 'terminalrc')

        if os.path.isfile(conf_file):
            f = open(conf_file, 'r')
            conf.readfp(f)
            f.close()
        else:
            conf.add_section('terminal')

        font = self._get_conf(conf, 'font', 'Monospace')
        vt.set_font(Pango.FontDescription(font))

        self._theme_colors = {"light": {'fg_color': '#000000',
                                        'bg_color': '#FFFFFF'},
                              "dark": {'fg_color': '#FFFFFF',
                                       'bg_color': '#000000'}}
        fg_color = self._theme_colors[self._theme_state]['fg_color']
        bg_color = self._theme_colors[self._theme_state]['bg_color']
        try:
            vt.set_colors(Gdk.color_parse(fg_color),
                          Gdk.color_parse(bg_color), [])
        except TypeError:
            # Vte 0.38 requires the colors set as a different type
            # in Fedora 21 we get a exception
            # TypeError: argument foreground: Expected Gdk.RGBA,
            # but got gi.overrides.Gdk.Color
            vt.set_colors(Gdk.RGBA(*Gdk.color_parse(fg_color).to_floats()),
                          Gdk.RGBA(*Gdk.color_parse(bg_color).to_floats()), [])

        blink = self._get_conf(conf, 'cursor_blink', False)
        vt.set_cursor_blink_mode(blink)

        bell = self._get_conf(conf, 'bell', False)
        vt.set_audible_bell(bell)

        scrollback_lines = self._get_conf(conf, 'scrollback_lines', 1000)
        vt.set_scrollback_lines(scrollback_lines)

        vt.set_allow_bold(True)

        scroll_key = self._get_conf(conf, 'scroll_on_keystroke', True)
        vt.set_scroll_on_keystroke(scroll_key)

        scroll_output = self._get_conf(conf, 'scroll_on_output', False)
        vt.set_scroll_on_output(scroll_output)

        if hasattr(vt, 'set_emulation'):
            # set_emulation is not available after vte commit
            # 4e253be9282829f594c8a55ca08d1299e80e471d
            emulation = self._get_conf(conf, 'emulation', 'xterm')
            vt.set_emulation(emulation)

        if hasattr(vt, 'set_visible_bell'):
            visible_bell = self._get_conf(conf, 'visible_bell', False)
            vt.set_visible_bell(visible_bell)

        conf.write(open(conf_file, 'w'))
    def __init__(self):
        self._root_path = os.path.join(env.get_profile_path(), 'datastore')

        if not os.path.exists(self._root_path):
            os.makedirs(self._root_path)

        self._create_if_needed(self.get_checksums_dir())
        self._create_if_needed(self.get_queue_path())
Beispiel #25
0
def get_log_file(bundle_id):
    log_dir = os.path.join(env.get_profile_path(), 'logs')
    log_files = glob.glob(os.path.join(log_dir, '%s*.log' % bundle_id))
    if len(log_files) > 0:
        sorted_log_files = sorted(log_files)
        return sorted_log_files[-1]
    else:
        return None
Beispiel #26
0
 def _write_to_temp_file(self, data):
     tmp_dir = os.path.join(env.get_profile_path(), 'data')
     f, file_path = tempfile.mkstemp(dir=tmp_dir)
     try:
         os.write(f, data)
     finally:
         os.close(f)
     return file_path
Beispiel #27
0
    def _create_file(self):
        activity_root = env.get_profile_path(self._activity.get_type())
        instance_path = os.path.join(activity_root, "instance")

        file_path = os.path.join(instance_path, "%i" % time.time())
        file_object = open(file_path, "w")

        return file_path, file_object
Beispiel #28
0
 def _write_to_temp_file(self, data):
     tmp_dir = os.path.join(env.get_profile_path(), 'data')
     f, file_path = tempfile.mkstemp(dir=tmp_dir)
     try:
         os.write(f, data)
     finally:
         os.close(f)
     return file_path
def get_profile():
    global _profile

    if not _profile:
        path = os.path.join(env.get_profile_path(), 'config')
        _profile = Profile(path)

    return _profile
Beispiel #30
0
    def _create_file(self):
        activity_root = env.get_profile_path(self._activity.get_type())
        instance_path = os.path.join(activity_root, "instance")

        file_path = os.path.join(instance_path, "%i" % time.time())
        file_object = open(file_path, "w")

        return file_path, file_object
Beispiel #31
0
def check_profile():
    profile = get_profile()

    path = os.path.join(env.get_profile_path(), 'config')
    if os.path.exists(path):
        profile.convert_profile()

    return profile.is_valid()
Beispiel #32
0
    def __init__(self):
        self._root_path = os.path.join(env.get_profile_path(), 'datastore')

        if not os.path.exists(self._root_path):
            os.makedirs(self._root_path)

        self._create_if_needed(self.get_checksums_dir())
        self._create_if_needed(self.get_queue_path())
Beispiel #33
0
def get_log_file(bundle_id):
    log_dir = os.path.join(env.get_profile_path(), 'logs')
    log_files = glob.glob(os.path.join(log_dir, '%s*.log' % bundle_id))
    if len(log_files) > 0:
        sorted_log_files = sorted(log_files)
        return sorted_log_files[-1]
    else:
        return None
Beispiel #34
0
    def __popup_cb(self, palette):
        stat = os.statvfs(env.get_profile_path())
        free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
        total_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS]

        fraction = (total_space - free_space) / float(total_space)
        self._progress_bar.props.fraction = fraction
        self._free_space_label.props.label = _("%(free_space)d MB Free") % {"free_space": free_space / (1024 * 1024)}
def get_profile():
    global _profile

    if not _profile:
        path = os.path.join(env.get_profile_path(), 'config')
        _profile = Profile(path)

    return _profile
Beispiel #36
0
def create_profile(user_profile):
    settings = Gio.Settings('org.sugarlabs.user')

    settings.set_string('nick', user_profile.nickname)

    colors = user_profile.colors
    if colors is None:
        colors = XoColor()
    settings.set_string('color', colors.to_string())

    if user_profile.gender is not None:
        settings.set_string('gender', user_profile.gender)
    else:
        settings.set_string('gender', '')

    settings.set_int('birth-timestamp',
                     calculate_birth_timestamp(user_profile.age))
    # settings.sync()

    # DEPRECATED
    from gi.repository import GConf
    client = GConf.Client.get_default()

    client.set_string('/desktop/sugar/user/nick', user_profile.nickname)

    client.set_string('/desktop/sugar/user/color', colors.to_string())

    if user_profile.gender is not None:
        client.set_string('/desktop/sugar/user/gender', user_profile.gender)

    client.set_int('/desktop/sugar/user/birth_timestamp',
                   calculate_birth_timestamp(user_profile.age))
    client.suggest_sync()

    if profile.get_pubkey() and profile.get_profile().privkey_hash:
        logging.info('Valid key pair found, skipping generation.')
        return

    # Generate keypair
    keypath = os.path.join(env.get_profile_path(), 'owner.key')
    if os.path.exists(keypath):
        os.rename(keypath, keypath + '.broken')
        logging.warning('Existing private key %s moved to %s.broken',
                        keypath, keypath)

    if os.path.exists(keypath + '.pub'):
        os.rename(keypath + '.pub', keypath + '.pub.broken')
        logging.warning('Existing public key %s.pub moved to %s.pub.broken',
                        keypath, keypath)

    logging.debug("Generating user keypair")

    cmd = "ssh-keygen -q -t dsa -f %s -C '' -N ''" % (keypath, )
    (s, o) = subprocess.getstatusoutput(cmd)
    if s != 0:
        logging.error('Could not generate key pair: %d %s', s, o)

    logging.debug("User keypair generated")
Beispiel #37
0
    def _create_file(self):
        activity_root = env.get_profile_path(self._activity.get_type())
        instance_path = os.path.join(activity_root, "instance")

        self._sequence += 1
        file_path = os.path.join(instance_path, "%d" % self._sequence)
        file_object = open(file_path, "wb")

        return file_path, file_object
Beispiel #38
0
def take_screenshot():
    tmp_dir = os.path.join(env.get_profile_path(), 'data')
    fd, file_path = tempfile.mkstemp(dir=tmp_dir)
    os.close(fd)

    window = Gdk.get_default_root_window()
    width, height = window.get_width(), window.get_height()

    screenshot_surface = Gdk.Window.create_similar_surface(
        window, cairo.CONTENT_COLOR, width, height)

    cr = cairo.Context(screenshot_surface)
    Gdk.cairo_set_source_window(cr, window, 0, 0)
    cr.paint()
    screenshot_surface.write_to_png(file_path)

    settings = Gio.Settings('org.sugarlabs.user')
    color = settings.get_string('color')

    content_title = None
    shell_model = shell.get_model()
    zoom_level = shell_model.zoom_level

    # TRANS: Nouns of what a screenshot contains
    if zoom_level == shell_model.ZOOM_MESH:
        content_title = _('Mesh')
    elif zoom_level == shell_model.ZOOM_GROUP:
        content_title = _('Group')
    elif zoom_level == shell_model.ZOOM_HOME:
        content_title = _('Home')
    elif zoom_level == shell_model.ZOOM_ACTIVITY:
        activity = shell_model.get_active_activity()
        if activity is not None:
            content_title = activity.get_title()
            if content_title is None:
                content_title = _('Activity')

    if content_title is None:
        title = _('Screenshot')
    else:
        title = _('Screenshot of \"%s\"') % content_title

    jobject = datastore.create()
    try:
        jobject.metadata['title'] = title
        jobject.metadata['keep'] = '0'
        jobject.metadata['buddies'] = ''
        jobject.metadata['preview'] = _get_preview_data(screenshot_surface)
        jobject.metadata['icon-color'] = color
        jobject.metadata['mime_type'] = 'image/png'
        jobject.file_path = file_path
        datastore.write(jobject, transfer_ownership=True)
    finally:
        jobject.destroy()
        del jobject

    return title
Beispiel #39
0
def take_screenshot():
    tmp_dir = os.path.join(env.get_profile_path(), 'data')
    fd, file_path = tempfile.mkstemp(dir=tmp_dir)
    os.close(fd)

    window = Gdk.get_default_root_window()
    width, height = window.get_width(), window.get_height()

    screenshot_surface = Gdk.Window.create_similar_surface(
        window, cairo.CONTENT_COLOR, width, height)

    cr = cairo.Context(screenshot_surface)
    Gdk.cairo_set_source_window(cr, window, 0, 0)
    cr.paint()
    screenshot_surface.write_to_png(file_path)

    settings = Gio.Settings('org.sugarlabs.user')
    color = settings.get_string('color')

    content_title = None
    shell_model = shell.get_model()
    zoom_level = shell_model.zoom_level

    # TRANS: Nouns of what a screenshot contains
    if zoom_level == shell_model.ZOOM_MESH:
        content_title = _('Mesh')
    elif zoom_level == shell_model.ZOOM_GROUP:
        content_title = _('Group')
    elif zoom_level == shell_model.ZOOM_HOME:
        content_title = _('Home')
    elif zoom_level == shell_model.ZOOM_ACTIVITY:
        activity = shell_model.get_active_activity()
        if activity is not None:
            content_title = activity.get_title()
            if content_title is None:
                content_title = _('Activity')

    if content_title is None:
        title = _('Screenshot')
    else:
        title = _('Screenshot of \"%s\"') % content_title

    jobject = datastore.create()
    try:
        jobject.metadata['title'] = title
        jobject.metadata['keep'] = '0'
        jobject.metadata['buddies'] = ''
        jobject.metadata['preview'] = _get_preview_data(screenshot_surface)
        jobject.metadata['icon-color'] = color
        jobject.metadata['mime_type'] = 'image/png'
        jobject.file_path = file_path
        datastore.write(jobject, transfer_ownership=True)
    finally:
        jobject.destroy()
        del jobject

    return title
Beispiel #40
0
    def __popup_cb(self, palette):
        stat = os.statvfs(env.get_profile_path())
        free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
        total_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS]

        fraction = (total_space - free_space) / float(total_space)
        self._progress_bar.props.fraction = fraction
        self._free_space_label.props.label = _('%(free_space)d MB Free') % \
            {'free_space': free_space / (1024 * 1024)}
Beispiel #41
0
    def __init__(self, activity, window_xid):
        self.parent_window_xid = window_xid

        url, title = get_help_url_and_title(activity)
        has_local_help = url is not None
        self._mode = _MODE_HELP if has_local_help else _MODE_SOCIAL_HELP

        Gtk.Window.__init__(self)
        box = Gtk.Box()
        box.set_orientation(Gtk.Orientation.VERTICAL)
        self.add(box)
        box.show()

        self.set_modal(True)
        self.set_decorated(False)
        self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
        self.set_border_width(style.LINE_WIDTH)
        self.set_has_resize_grip(False)

        width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2
        height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2
        self.set_size_request(width, height)

        self.connect("realize", self.__realize_cb)
        self.connect("hide", self.__hide_cb)
        self.connect("key-press-event", self.__key_press_event_cb)

        self._toolbar = Toolbar(title, has_local_help)
        box.pack_start(self._toolbar, False, False, 0)
        self._toolbar.show()
        self._toolbar.connect("stop-clicked", self.__stop_clicked_cb)
        self._toolbar.connect("mode-changed", self.__mode_changed_cb)

        context = WebKit2.WebContext.get_default()
        cookie_manager = context.get_cookie_manager()
        cookie_manager.set_persistent_storage(
            os.path.join(env.get_profile_path(), "social-help.cookies"), WebKit2.CookiePersistentStorage.SQLITE
        )

        self._webview = WebKit2.WebView()
        self._webview.get_context().register_uri_scheme("help", self.__app_scheme_cb, None)
        self._toolbar.bind_webview(self._webview)

        box.pack_start(self._webview, True, True, 0)
        self._webview.show()

        language = self._get_current_language()
        self._help_state = None
        if has_local_help:
            self._help_url = "help://" + self._get_help_file(language, url)

        self._social_help_uri = "{}/goto/{}".format(get_social_help_server(), activity.get_bundle_id())
        self._social_help_state = None

        self._webview.connect("load-changed", self.__load_changed_cb)
        self._load_mode(self._mode)
Beispiel #42
0
    def _get_space(self):
        stat = os.statvfs(env.get_profile_path())
        free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
        total_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS]

        free_space = self._get_MBs(free_space)
        total_space = self._get_MBs(total_space)
        used_space = total_space - free_space

        return free_space, used_space, total_space
Beispiel #43
0
    def _get_space(self):
        stat = os.statvfs(env.get_profile_path())
        free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
        total_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS]

        free_space = self._get_MBs(free_space)
        total_space = self._get_MBs(total_space)
        used_space = total_space - free_space

        return free_space, used_space, total_space
Beispiel #44
0
    def read_config(self):
        self.conf = configparser.ConfigParser()
        self.conf_file = os.path.join(env.get_profile_path(), 'terminalrc')

        if os.path.isfile(self.conf_file):
            f = open(self.conf_file, 'r')
            self.conf.readfp(f)
            f.close()
        else:
            self.conf.add_section('terminal')
Beispiel #45
0
def cleanup_temporary_files():
    try:
        # Remove temporary files. See http://bugs.sugarlabs.org/ticket/1876
        data_dir = os.path.join(env.get_profile_path(), 'data')
        shutil.rmtree(data_dir, ignore_errors=True)
        os.makedirs(data_dir)
    except OSError, e:
        # temporary files cleanup is not critical; it should not prevent
        # sugar from starting if (for example) the disk is full or read-only.
        print 'temporary files cleanup failed: %s' % e
Beispiel #46
0
def cleanup_temporary_files():
    try:
        # Remove temporary files. See http://bugs.sugarlabs.org/ticket/1876
        data_dir = os.path.join(env.get_profile_path(), 'data')
        shutil.rmtree(data_dir, ignore_errors=True)
        os.makedirs(data_dir)
    except OSError, e:
        # temporary files cleanup is not critical; it should not prevent
        # sugar from starting if (for example) the disk is full or read-only.
        print 'temporary files cleanup failed: %s' % e
Beispiel #47
0
def handle_key_press(key):
    tmp_dir = os.path.join(env.get_profile_path(), 'data')
    fd, file_path = tempfile.mkstemp(dir=tmp_dir)
    os.close(fd)

    window = Gdk.get_default_root_window()
    width, height = window.get_width(), window.get_height()

    window_cr = Gdk.cairo_create(window)
    window_surface = window_cr.get_target()
    screenshot_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
    cr = cairo.Context(screenshot_surface)
    cr.set_source_surface(window_surface)
    cr.paint()
    screenshot_surface.write_to_png(file_path)

    client = GConf.Client.get_default()
    color = client.get_string('/desktop/sugar/user/color')

    content_title = None
    shell_model = shell.get_model()
    zoom_level = shell_model.zoom_level

    # TRANS: Nouns of what a screenshot contains
    if zoom_level == shell_model.ZOOM_MESH:
        content_title = _('Mesh')
    elif zoom_level == shell_model.ZOOM_GROUP:
        content_title = _('Group')
    elif zoom_level == shell_model.ZOOM_HOME:
        content_title = _('Home')
    elif zoom_level == shell_model.ZOOM_ACTIVITY:
        activity = shell_model.get_active_activity()
        if activity != None:
            content_title = activity.get_title()
            if content_title == None:
                content_title = _('Activity')

    if content_title is None:
        title = _('Screenshot')
    else:
        title = _('Screenshot of \"%s\"') % content_title

    jobject = datastore.create()
    try:
        jobject.metadata['title'] = title
        jobject.metadata['keep'] = '0'
        jobject.metadata['buddies'] = ''
        jobject.metadata['preview'] = _get_preview_data(screenshot_surface)
        jobject.metadata['icon-color'] = color
        jobject.metadata['mime_type'] = 'image/png'
        jobject.file_path = file_path
        datastore.write(jobject, transfer_ownership=True)
    finally:
        jobject.destroy()
        del jobject
Beispiel #48
0
def handle_key_press(key):
    tmp_dir = os.path.join(env.get_profile_path(), 'data')
    fd, file_path = tempfile.mkstemp(dir=tmp_dir)
    os.close(fd)

    window = Gdk.get_default_root_window()
    width, height = window.get_width(), window.get_height()

    window_cr = Gdk.cairo_create(window)
    window_surface = window_cr.get_target()
    screenshot_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
    cr = cairo.Context(screenshot_surface)
    cr.set_source_surface(window_surface)
    cr.paint()
    screenshot_surface.write_to_png(file_path)

    client = GConf.Client.get_default()
    color = client.get_string('/desktop/sugar/user/color')

    content_title = None
    shell_model = shell.get_model()
    zoom_level = shell_model.zoom_level

    # TRANS: Nouns of what a screenshot contains
    if zoom_level == shell_model.ZOOM_MESH:
        content_title = _('Mesh')
    elif zoom_level == shell_model.ZOOM_GROUP:
        content_title = _('Group')
    elif zoom_level == shell_model.ZOOM_HOME:
        content_title = _('Home')
    elif zoom_level == shell_model.ZOOM_ACTIVITY:
        activity = shell_model.get_active_activity()
        if activity != None:
            content_title = activity.get_title()
            if content_title == None:
                content_title = _('Activity')

    if content_title is None:
        title = _('Screenshot')
    else:
        title = _('Screenshot of \"%s\"') % content_title

    jobject = datastore.create()
    try:
        jobject.metadata['title'] = title
        jobject.metadata['keep'] = '0'
        jobject.metadata['buddies'] = ''
        jobject.metadata['preview'] = _get_preview_data(screenshot_surface)
        jobject.metadata['icon-color'] = color
        jobject.metadata['mime_type'] = 'image/png'
        jobject.file_path = file_path
        datastore.write(jobject, transfer_ownership=True)
    finally:
        jobject.destroy()
        del jobject
Beispiel #49
0
    def _get_space(self):
        path = env.get_profile_path()
        stat = os.statvfs(path)
        free_space = stat.f_bsize * stat.f_bavail
        total_space = stat.f_bsize * stat.f_blocks

        free_space = self._get_MBs(free_space)
        total_space = self._get_MBs(total_space)
        used_space = total_space - free_space

        return free_space, used_space, total_space
Beispiel #50
0
    def __accept_activate_cb(self, menu_item):
        #TODO: figure out the best place to get rid of that temp file
        extension = mime.get_primary_extension(self.file_transfer.mime_type)
        if extension is None:
            extension = '.bin'
        fd, file_path = tempfile.mkstemp(suffix=extension,
                prefix=self._sanitize(self.file_transfer.title),
                dir=os.path.join(env.get_profile_path(), 'data'))
        os.close(fd)
        os.unlink(file_path)

        self.file_transfer.accept(file_path)
Beispiel #51
0
def check_profile():
    profile = get_profile()

    path = os.path.join(os.path.expanduser('~/.sugar'), 'debug')
    if not os.path.exists(path):
        profile.create_debug_file()

    path = os.path.join(env.get_profile_path(), 'config')
    if os.path.exists(path):
        profile.convert_profile()

    return profile.is_valid()
Beispiel #52
0
def create_profile(user_profile):
    settings = Gio.Settings('org.sugarlabs.user')

    if user_profile.nickname in [None, '']:
        nick = settings.get_string('nick')
        if nick is not None:
            logging.debug('recovering old nickname %s' % (nick))
            user_profile.nickname = nick
    settings.set_string('nick', user_profile.nickname)

    colors = user_profile.colors
    if colors is None:
        colors = XoColor()
    settings.set_string('color', colors.to_string())

    genderpicker.save_gender(user_profile.gender)

    agepicker.save_age(user_profile.age)

    # DEPRECATED
    from gi.repository import GConf
    client = GConf.Client.get_default()

    client.set_string('/desktop/sugar/user/nick', user_profile.nickname)

    client.set_string('/desktop/sugar/user/color', colors.to_string())

    client.suggest_sync()

    if profile.get_pubkey() and profile.get_profile().privkey_hash:
        logging.info('Valid key pair found, skipping generation.')
        return

    # Generate keypair
    keypath = os.path.join(env.get_profile_path(), 'owner.key')
    if os.path.exists(keypath):
        os.rename(keypath, keypath + '.broken')
        logging.warning('Existing private key %s moved to %s.broken', keypath,
                        keypath)

    if os.path.exists(keypath + '.pub'):
        os.rename(keypath + '.pub', keypath + '.pub.broken')
        logging.warning('Existing public key %s.pub moved to %s.pub.broken',
                        keypath, keypath)

    logging.debug("Generating user keypair")

    cmd = "ssh-keygen -q -t dsa -f %s -C '' -N ''" % (keypath, )
    (s, o) = commands.getstatusoutput(cmd)
    if s != 0:
        logging.error('Could not generate key pair: %d %s', s, o)

    logging.debug("User keypair generated")
Beispiel #53
0
    def __accept_activate_cb(self, menu_item):
        #TODO: figure out the best place to get rid of that temp file
        extension = mime.get_primary_extension(self.file_transfer.mime_type)
        if extension is None:
            extension = '.bin'
        fd, file_path = tempfile.mkstemp(suffix=extension,
                prefix=self._sanitize(self.file_transfer.title),
                dir=os.path.join(env.get_profile_path(), 'data'))
        os.close(fd)
        os.unlink(file_path)

        self.file_transfer.accept(file_path)
Beispiel #54
0
def create_profile(user_profile):
    settings = Gio.Settings('org.sugarlabs.user')

    if user_profile.nickname in [None, '']:
        nick = settings.get_string('nick')
        if nick is not None:
            logging.debug('recovering old nickname %s' % (nick))
            user_profile.nickname = nick
    settings.set_string('nick', user_profile.nickname)

    colors = user_profile.colors
    if colors is None:
        colors = XoColor()
    settings.set_string('color', colors.to_string())

    genderpicker.save_gender(user_profile.gender)

    agepicker.save_age(user_profile.age)

    # DEPRECATED
    from gi.repository import GConf
    client = GConf.Client.get_default()

    client.set_string('/desktop/sugar/user/nick', user_profile.nickname)

    client.set_string('/desktop/sugar/user/color', colors.to_string())

    client.suggest_sync()

    if profile.get_pubkey() and profile.get_profile().privkey_hash:
        logging.info('Valid key pair found, skipping generation.')
        return

    # Generate keypair
    keypath = os.path.join(env.get_profile_path(), 'owner.key')
    if os.path.exists(keypath):
        os.rename(keypath, keypath + '.broken')
        logging.warning('Existing private key %s moved to %s.broken',
                        keypath, keypath)

    if os.path.exists(keypath + '.pub'):
        os.rename(keypath + '.pub', keypath + '.pub.broken')
        logging.warning('Existing public key %s.pub moved to %s.pub.broken',
                        keypath, keypath)

    logging.debug("Generating user keypair")

    cmd = "ssh-keygen -q -t dsa -f %s -C '' -N ''" % (keypath, )
    (s, o) = commands.getstatusoutput(cmd)
    if s != 0:
        logging.error('Could not generate key pair: %d %s', s, o)

    logging.debug("User keypair generated")
Beispiel #55
0
 def get_file_path(self, fetch=True):
     # we have to create symlink since its a common practice
     # to create hardlinks to jobject files
     # and w/o this, it wouldn't work since we have file from mounted device
     if self._file_path is None:
         data_path = os.path.join(env.get_profile_path(), 'data')
         self._file_path = tempfile.mktemp(prefix='rawobject',
                                           dir=data_path)
         if not os.path.exists(data_path):
             os.makedirs(data_path)
         os.symlink(self.object_id, self._file_path)
     return self._file_path
Beispiel #56
0
def check_profile():
    profile = get_profile()

    path = os.path.join(os.path.expanduser('~/.sugar'), 'debug')
    if not os.path.exists(path):
        profile.create_debug_file()

    path = os.path.join(env.get_profile_path(), 'config')
    if os.path.exists(path):
        profile.convert_profile()

    return profile.is_valid()
 def get_file_path(self, fetch=True):
     # we have to create symlink since its a common practice
     # to create hardlinks to jobject files
     # and w/o this, it wouldn't work since we have file from mounted device
     if self._file_path is None:
         data_path = os.path.join(env.get_profile_path(), 'data')
         self._file_path = tempfile.mktemp(
             prefix='rawobject', dir=data_path)
         if not os.path.exists(data_path):
             os.makedirs(data_path)
         os.symlink(self.object_id, self._file_path)
     return self._file_path