class ShareAccept():
    def __init__(self):
        print "init"
        self.sd = SyncDaemonTool()

        self.detect_shares()

    @defer.inlineCallbacks
    def detect_shares(self):
        print "Detecting shares..."
        self.sd.refresh_shares()
        l = yield self.sd.get_shares()
        for s in l:
            volume_id = str(s["volume_id"])
            if s["accepted"] == "":
                print "...FOUND NEW SHARE: " + str(s["name"]) + " (" + str(
                    s["volume_id"]) + ")"
                print "...accepting share: " + volume_id
                res = yield self.sd.accept_share(volume_id)
            if s["subscribed"] == "":
                print "...subscribing to share: " + volume_id
                sub = yield self.sd.subscribe_share(volume_id)
                print "...done!"
        print "Completed."
        reactor.stop()
class ShareAccept():
	def __init__(self):
		print "init"
		self.sd = SyncDaemonTool()

		self.detect_shares()

	@defer.inlineCallbacks
	def detect_shares(self):
		print "Detecting shares..."
		self.sd.refresh_shares()
		l = yield self.sd.get_shares()
		for s in l:
			volume_id = str(s["volume_id"])
			if s["accepted"] == "":
				print "...FOUND NEW SHARE: " + str(s["name"]) + " (" + str(s["volume_id"]) + ")"
				print "...accepting share: " + volume_id
				res = yield self.sd.accept_share(volume_id)
			if s["subscribed"] == "":
				print "...subscribing to share: " + volume_id
				sub = yield self.sd.subscribe_share(volume_id)
				print "...done!"
		print "Completed."
		reactor.stop()		
Exemplo n.º 3
0
    def __init__(self, msd):
        # magicicada's syncdaemon
        self.msd = msd
        logger.info("DBus interface starting")
        self._public_files_deferred = None

        # set up dbus and related stuff
        loop = DBusGMainLoop(set_as_default=True)
        self._bus = bus = SessionBus(mainloop=loop)
        self.sync_daemon_tool = SyncDaemonTool(bus)

        # hook up for signals and store info for the shutdown
        _signals = [
            (self._on_status_changed, 'Status', 'StatusChanged'),
            (self._on_queue_added, 'Status', 'RequestQueueAdded'),
            (self._on_queue_removed, 'Status', 'RequestQueueRemoved'),
            (self._on_upload_progress, 'Status', 'UploadFileProgress'),
            (self._on_download_progress, 'Status', 'DownloadFileProgress'),
            (self._on_folder_created, 'Folders', 'FolderCreated'),
            (self._on_folder_deleted, 'Folders', 'FolderDeleted'),
            (self._on_folder_subscribed, 'Folders', 'FolderSubscribed'),
            (self._on_folder_unsubscribed, 'Folders', 'FolderUnSubscribed'),
            (self._on_share_created, 'Shares', 'ShareCreated'),
            (self._on_share_deleted, 'Shares', 'ShareDeleted'),
            (self._on_share_changed, 'Shares', 'ShareChanged'),
            (self._on_public_files_changed, 'PublicFiles',
                                            'PublicAccessChanged'),
        ]
        self._dbus_matches = []
        for method, dbus_lastname, signal_name in _signals:
            if dbus_lastname is None:
                dbus_interface = None
            else:
                dbus_interface = 'com.ubuntuone.SyncDaemon.' + dbus_lastname
            match = bus.add_signal_receiver(method,
                                            dbus_interface=dbus_interface,
                                            signal_name=signal_name)
            self._dbus_matches.append((match, dbus_interface, signal_name))
Exemplo n.º 4
0
 def __init__(self, success_callback, failure_callback):
     self.success_callback = success_callback
     self.failure_callback = failure_callback
     self.path = None
     if SyncDaemonTool:
         self.sd = SyncDaemonTool(bus=dbus.SessionBus())
Exemplo n.º 5
0
class Uploader(object):
    def __init__(self, success_callback, failure_callback):
        self.success_callback = success_callback
        self.failure_callback = failure_callback
        self.path = None
        if SyncDaemonTool:
            self.sd = SyncDaemonTool(bus=dbus.SessionBus())

    def uploadFile(self, path):
        self.path = path
        if not SyncDaemonTool:
            failure_callback(path, "Could not find Ubuntu One library (python-ubuntuone-client)")
            return
        
        # First, confirm Ubuntu One is connected
        d = self.sd.get_status()
        d.addErrback(self.__failure)
        d.addCallback(self.__got_status)

    def __failure(self, *args):
        self.failure_callback(self.path, "Problem uploading to Ubuntu One: %s" % str(args))

    def __got_status(self, state):
        if state["is_online"]:
            self.__copy_file()
        else:
            # not online, so try to connect
            self.sig_status_changed = self.sd.bus.add_signal_receiver(
                handler_function=self.__status_changed, signal_name="StatusChanged",
                dbus_interface=DBUS_IFACE_STATUS_NAME, path='/status')
            d = self.sd.connect()
            d.addErrback(self.__failure)

    def __status_changed(self, status):
        if status["is_online"]:
            # We are connected; continue
            self.sig_status_changed.remove()
            self.__copy_file()
            return
        if status["is_error"]:
            # We are not connected, and not going to be without user fixes
            self.sig_status_changed.remove()
            self.__failure("Could not connect to Ubuntu One")
            return

    def __copy_file(self):
        # First, create a folder to put the copy of the specified file in
        fol = os.path.expanduser("~/Ubuntu One/Gwibber Uploads")
        try:
            os.makedirs(fol)
        except OSError:
            if not os.path.isdir(fol):
                self.__failure("Could not create Gwibber Uploads folder in Ubuntu One")
                return
            # OSError is OK if the folder already existed
        fdir, ffullname = os.path.split(self.path)
        fname, fext = os.path.splitext(ffullname)
        src = gio.File(self.path)
        dest = gio.File(os.path.join(fol, ffullname))
        
        # We connect to the UploadFinished signal from syncdaemon here,
        # before we even copy the file, so we know that it's right.
        self.sig_upload_finished = self.sd.bus.add_signal_receiver(
            handler_function=self.__file_uploaded, signal_name="UploadFinished",
            dbus_interface=DBUS_IFACE_STATUS_NAME, path='/status')
        
        try:
            src.copy(dest)
        except gio.Error:
            # file with this name exists. Try creating a file with a number in
            differentiator = 1
            while 1:
                try:
                    dest = gio.File(os.path.join(fol, "%s (%s)%s" % (fname, differentiator, fext)))
                    src.copy(dest)
                except gio.Error:
                    differentiator += 1
                else:
                    break
        self.u1path = dest.get_path() # the actual path in ~/Ubuntu One

    def __file_uploaded(self, path, info):
        if path == self.u1path:
            # stop listening to the signal
            self.sig_upload_finished.remove()
            # publish the file
            d = self.sd.change_public_access(path, True)
            d.addCallback(self.__published)
            d.addErrback(self.__failure)

    def __published(self, info):
        self.success_callback(self.path, info["public_url"])
Exemplo n.º 6
0
 def initWithDelegate_(self, delegate):
     self = super(U1FinderLib, self).init()
     self.sync_daemon_tool = SyncDaemonTool(None)
     self.delegate = delegate
     cfreactor.install()
     return self
Exemplo n.º 7
0
class U1FinderLib(NSObject):

    ##
    # Default constructor.
    @objc.typedSelector('@@:@')
    def initWithDelegate_(self, delegate):
        self = super(U1FinderLib, self).init()
        self.sync_daemon_tool = SyncDaemonTool(None)
        self.delegate = delegate
        cfreactor.install()
        return self

    ##
    # Returns the list of the shared volumes in a NSArray<NSString>. Example:
    #
    # [
    #    @"/Users/jose/Ubuntu One",
    #    @"/Users/jose/Pictures"
    # ]
    @objc.typedSelector('v@:')
    def volumeList(self):
        d = self.sync_daemon_tool.get_folders()
        d.addCallback(lambda r: volume_list(r, self.delegate))
        return None

    ##
    # Returns a NSArray<NSString> whit all the files that are being uploaded. Example:
    # [
    #     @"/Users/jose/Ubuntu One/Document.pdf",
    #     @"/Users/jose/Pictures/Image.png"
    # }
    @objc.typedSelector('v@:')
    def currentUploads(self):
        d = self.sync_daemon_tool.get_current_uploads()
        d.addCallback(lambda r: get_uploads(r, self.delegate))
        return None

    ##
    # Like currentUploads() but with the downloads.
    @objc.typedSelector('v@:')
    def currentDownloads(self):
        d = self.sync_daemon_tool.get_current_downloads()
        d.addCallback(lambda r: get_downloads(r, self.delegate))
        return None

    ##
    # Indicates if the specified file is public or not.
    @objc.typedSelector('@@:@')
    def isFilePublic_(self, filePath):
        d = self.sync_daemon_tool.get_public_files()
        d.addCallback(lambda r: file_is_public(r, filePath, self.delegate))
        return None

    ##
    # Publish or unpublish the specified file.
    @objc.typedSelector('v@:@B')
    def changeFile_visibillity_(self, filePath, isPublic):
        self.sync_daemon_tool.change_public_access(os.path.abspath(filePath),
                                                   isPublic)
        return None

    ##
    # Returns the link (NSString) of a public file or nil if the file is not public.
    @objc.typedSelector('@@:@')
    def getPublicLinkOfFile_(self, filePath):
        d = self.sync_daemon_tool.get_public_files()
        d.addCallback(lambda r: get_public_files(r, filePath, self.delegate))
        return None

    ##
    # Synchronizes the specified folder
    @objc.typedSelector('@@:@')
    def synchronizeFolderAtPath_(self, folderPath):
        d = self.sync_daemon_tool.create_folder(os.path.abspath(folderPath))
        d.addCallback(lambda r: folder_synchronized(r, self.delegate))
        return None

    ##
    # Unsuscribes the specified folder.
    @objc.typedSelector('@@:@')
    def unsuscribeFolderAtPath_(self, folderPath):
        d = self.sync_daemon_tool.get_folders()
        d.addCallback(lambda r: unsuscribe_volume_list(
            r, folderPath, self.sync_daemon_tool, self.delegate))
        return None
    def __init__(self):
        print "init"
        self.sd = SyncDaemonTool()

        self.detect_shares()
Exemplo n.º 9
0
class DBusInterface(object):
    """The DBus Interface to Ubuntu One's SyncDaemon."""

    def __init__(self, msd):
        # magicicada's syncdaemon
        self.msd = msd
        logger.info("DBus interface starting")
        self._public_files_deferred = None

        # set up dbus and related stuff
        loop = DBusGMainLoop(set_as_default=True)
        self._bus = bus = SessionBus(mainloop=loop)
        self.sync_daemon_tool = SyncDaemonTool(bus)

        # hook up for signals and store info for the shutdown
        _signals = [
            (self._on_status_changed, 'Status', 'StatusChanged'),
            (self._on_queue_added, 'Status', 'RequestQueueAdded'),
            (self._on_queue_removed, 'Status', 'RequestQueueRemoved'),
            (self._on_upload_progress, 'Status', 'UploadFileProgress'),
            (self._on_download_progress, 'Status', 'DownloadFileProgress'),
            (self._on_folder_created, 'Folders', 'FolderCreated'),
            (self._on_folder_deleted, 'Folders', 'FolderDeleted'),
            (self._on_folder_subscribed, 'Folders', 'FolderSubscribed'),
            (self._on_folder_unsubscribed, 'Folders', 'FolderUnSubscribed'),
            (self._on_share_created, 'Shares', 'ShareCreated'),
            (self._on_share_deleted, 'Shares', 'ShareDeleted'),
            (self._on_share_changed, 'Shares', 'ShareChanged'),
            (self._on_public_files_changed, 'PublicFiles',
                                            'PublicAccessChanged'),
        ]
        self._dbus_matches = []
        for method, dbus_lastname, signal_name in _signals:
            if dbus_lastname is None:
                dbus_interface = None
            else:
                dbus_interface = 'com.ubuntuone.SyncDaemon.' + dbus_lastname
            match = bus.add_signal_receiver(method,
                                            dbus_interface=dbus_interface,
                                            signal_name=signal_name)
            self._dbus_matches.append((match, dbus_interface, signal_name))

    def shutdown(self):
        """Shut down the SyncDaemon."""
        logger.info("DBus interface going down")

        # remove the signals from DBus
        remove = self._bus.remove_signal_receiver
        for match, dbus_interface, signal in self._dbus_matches:
            remove(match, dbus_interface=dbus_interface, signal_name=signal)

    def _process_status(self, state):
        """Transform status information."""
        name = state['name']
        description = state['description']
        is_error = bool(state['is_error'])
        is_connected = bool(state['is_connected'])
        is_online = bool(state['is_online'])
        queues = state['queues']
        connection = state['connection']
        return (name, description, is_error, is_connected,
                is_online, queues, connection)

    @retryable
    def get_status(self):
        """Get SD status."""
        logger.info("Getting status")
        d = self.sync_daemon_tool.get_status()
        d.addCallback(self._process_status)
        return d

    @retryable
    @defer.inlineCallbacks
    def get_free_space(self, volume_id):
        """Get the free space for a volume."""
        result = yield self.sync_daemon_tool.free_space(volume_id)
        logger.info("Free space for volume %r is %r", volume_id, result)
        defer.returnValue(result)

    @retryable
    @defer.inlineCallbacks
    def get_real_shares_dir(self):
        """Get the real directory for the shares."""
        result = yield self.sync_daemon_tool.get_shares_dir()
        logger.info("Real shares dir: %r", result)
        defer.returnValue(result)

    @retryable
    @defer.inlineCallbacks
    def get_link_shares_dir(self):
        """Get the link directory for the shares."""
        result = yield self.sync_daemon_tool.get_shares_dir_link()
        logger.info("Link shares dir: %r", result)
        defer.returnValue(result)

    def _process_transfers(self, transfers, progress):
        """Process downloads or uploads to keep useful info only."""
        r = [Transfer(t['path'], int(t[progress]), int(t['deflated_size']))
             for t in transfers if 'deflated_size' in t]
        return r

    @retryable
    @defer.inlineCallbacks
    def get_current_downloads(self):
        """Get the current_downloads."""
        result = yield self.sync_daemon_tool.get_current_downloads()
        processed = self._process_transfers(result, 'n_bytes_read')
        logger.info("Get current downloads: %d items", len(processed))
        defer.returnValue(processed)

    @retryable
    @defer.inlineCallbacks
    def get_current_uploads(self):
        """Get the current_uploads."""
        result = yield self.sync_daemon_tool.get_current_uploads()
        processed = self._process_transfers(result, 'n_bytes_written')
        logger.info("Get current uploads: %d items", len(processed))
        defer.returnValue(processed)

    def _on_status_changed(self, state):
        """Call the SD callback."""
        logger.info("Received Status changed")
        logger.debug("Status changed data: %r", state)
        data = self._process_status(state)
        self.msd.on_sd_status_changed(*data)

    def _on_queue_added(self, op_name, op_id, op_data):
        """Call the SD callback."""
        logger.debug("Received Queue added: %r [%s] %s",
                     op_name, op_id, op_data)
        self.msd.on_sd_queue_added(op_name, op_id, op_data)

    def _on_queue_removed(self, op_name, op_id, op_data):
        """Call the SD callback."""
        logger.debug("Received Queue removed: %r [%s] %s",
                     op_name, op_id, op_data)
        self.msd.on_sd_queue_removed(op_name, op_id, op_data)

    def _on_upload_progress(self, path, op_data):
        """Call the SD callback."""
        logger.debug("Received Upload progress: %r %s", path, op_data)
        transf = Transfer(path, int(op_data['n_bytes_written']),
                          int(op_data['deflated_size']))
        self.msd.on_sd_upload_progress(transf)

    def _on_download_progress(self, path, op_data):
        """Call the SD callback."""
        logger.debug("Received Download progress: %r %s", path, op_data)
        transf = Transfer(path, int(op_data['n_bytes_read']),
                          int(op_data['deflated_size']))
        self.msd.on_sd_download_progress(transf)

    def _on_folder_created(self, _):
        """Call the SD callback."""
        logger.info("Received Folder created")
        self.msd.on_sd_folders_changed()

    def _on_folder_deleted(self, _):
        """Call the SD callback."""
        logger.info("Received Folder deleted")
        self.msd.on_sd_folders_changed()

    def _on_folder_subscribed(self, _):
        """Call the SD callback."""
        logger.info("Received Folder subscribed")
        self.msd.on_sd_folders_changed()

    def _on_folder_unsubscribed(self, _):
        """Call the SD callback."""
        logger.info("Received Folder unsubscribed")
        self.msd.on_sd_folders_changed()

    def _on_share_created(self, _):
        """Call the SD callback."""
        logger.info("Received Share created")
        self.msd.on_sd_shares_changed()

    def _on_share_deleted(self, _):
        """Call the SD callback."""
        logger.info("Received Share deleted")
        self.msd.on_sd_shares_changed()

    def _on_share_changed(self, _):
        """Call the SD callback."""
        logger.info("Received Share changed")
        self.msd.on_sd_shares_changed()

    def _on_public_files_changed(self, data):
        """Call the SD callback."""
        logger.debug("Received Public Files changed: %s", data)
        pf = PublicFilesData(volume=data['share_id'], node=data['node_id'],
                             path=data['path'], public_url=data['public_url'])
        is_public = bool(data['is_public'])
        self.msd.on_sd_public_files_changed(pf, is_public)

    def _on_public_files_list(self, data):
        """Call the SD callback."""
        logger.info("Received Public Files list (%d)", len(data))
        processed = []
        for d in data:
            logger.debug("    Public Files data: %s", d)
            p = PublicFilesData(volume=d['volume_id'], node=d['node_id'],
                                path=d['path'], public_url=d['public_url'])
            processed.append(p)

        return processed

    @defer.inlineCallbacks
    def get_public_files(self):
        """Ask the Public Files info to syncdaemon."""
        try:
            result = yield self.sync_daemon_tool.get_public_files()
            logger.debug("Public files asked ok.")
        except AttributeError:
            logger.warning('Method sdtool.get_public_files is not available, '
                           'trying old one directly from dbus.')
            result = yield self.get_public_files_old()
        except:
            logger.exception("Public files finished with error:")
            result = []

        defer.returnValue(self._on_public_files_list(result))

    def get_public_files_old(self):
        """Ask the Public Files info to syncdaemon (old approach)."""
        # yes, they can be imported! pylint: disable=F0401,E0611,W0404
        from ubuntuone.platform.tools import DBusClient, ErrorSignal
        from ubuntuone.platform.dbus_interface import \
            DBUS_IFACE_PUBLIC_FILES_NAME
        client = DBusClient(self._bus, '/publicfiles',
                            DBUS_IFACE_PUBLIC_FILES_NAME)

        # note that these callbacks do not come with the requested info, the
        # method just will return None, and the real info will come later
        # in a signal

        def call_done(result):
            """Call was succesful."""
            logger.debug("Public files asked ok.")

        def call_error(error):
            """Call was not succesful."""
            logger.error("Public files asked with error: %s", error)

        d = self.sync_daemon_tool.wait_for_signal('PublicFilesList',
                                                  filter=lambda _: True)

        client.call_method('get_public_files',
                           reply_handler=call_done,
                           error_handler=call_error)
        return d

    @retryable
    def get_queue_content(self):
        """Get the queue content from SDT."""
        logger.info("Getting queue content")
        return self.sync_daemon_tool.waiting()

    @retryable
    def get_folders(self):
        """Get the folders info from SDT."""

        def process(data):
            """Enhance data format."""
            logger.info("Processing Folders items (%d)", len(data))
            all_items = []
            for d in data:
                logger.debug("    Folders data: %r", d)
                f = self._get_folder_data(d)
                all_items.append(f)
            return all_items

        logger.info("Getting folders")
        d = self.sync_daemon_tool.get_folders()
        d.addCallback(process)
        return d

    def start(self):
        """Start SDT."""
        logger.info("Calling start")
        return self.sync_daemon_tool.start()

    def quit(self):
        """Stop SDT."""
        logger.info("Calling quit")
        return self.sync_daemon_tool.quit()

    def connect(self):
        """Connect SDT."""
        logger.info("Calling connect")
        return self.sync_daemon_tool.connect()

    def disconnect(self):
        """Disconnect SDT."""
        logger.info("Calling disconnect")
        return self.sync_daemon_tool.disconnect()

    @defer.inlineCallbacks
    def is_sd_started(self):
        """Find out if SD is active in the system."""
        started = yield is_already_running()
        logger.info("Checking if SD is started: %s", started)
        defer.returnValue(started)

    def _process_share_info(self, data):
        """Process share data."""
        all_items = []
        for d in data:
            logger.debug("    Share data: %r", d)

            # some processing
            dfb = d['free_bytes']
            free_bytes = None if dfb == '' else int(dfb)

            s = ShareData(
                accepted=bool(d['accepted']),
                access_level=d['access_level'],
                free_bytes=free_bytes,
                name=d['name'],
                node_id=d['node_id'],
                other_username=d['other_username'],
                other_visible_name=d['other_visible_name'],
                path=d['path'],
                volume_id=d['volume_id'],
                subscribed=bool(d['subscribed']),
            )
            all_items.append(s)
        return all_items

    @retryable
    def get_shares_to_me(self):
        """Get the shares to me ('shares') info from SDT."""

        def process(data):
            """Enhance data format."""
            logger.info("Processing Shares To Me items (%d)", len(data))
            return self._process_share_info(data)

        logger.info("Getting shares to me")
        d = self.sync_daemon_tool.get_shares()
        d.addCallback(process)
        return d

    @retryable
    def get_shares_to_others(self):
        """Get the shares to others ('shared') info from SDT."""

        def process(data):
            """Enhance data format."""
            logger.info("Processing Shares To Others items (%d)", len(data))
            return self._process_share_info(data)

        logger.info("Getting shares to others")
        d = self.sync_daemon_tool.list_shared()
        d.addCallback(process)
        return d

    @retryable
    def get_metadata(self, path):
        """Return the raw metadata."""
        logger.info("Getting metadata for %r", path)

        def fix_failure(failure):
            """Get the failure and return a nice message."""
            if failure.check(dbus.exceptions.DBusException):
                if failure.value.get_dbus_name() == DBUSERR_PYKEYERROR:
                    return NOT_SYNCHED_PATH
            return failure

        def process(metadata):
            """Process the metadata."""
            logger.debug("Got metadata for path %r: %r", path, metadata)
            return dict(metadata)

        d = self.sync_daemon_tool.get_metadata(path)
        d.addCallbacks(process, fix_failure)
        return d

    @retryable
    @defer.inlineCallbacks
    def _answer_share(self, share_id, method, action_name):
        """Effectively accept or reject a share."""
        logger.debug("%s share %s started", action_name, share_id)
        try:
            result = yield method(share_id)
        except Exception, e:
            if len(e.args) == 2 and len(e.args[1]) > 1:
                error = "%s (%s)" % (e.args[0], e.args[1][1])
            else:
                error = str(e.args[0])
            logger.debug("%s share %s crashed: %s",
                         action_name, share_id, error)
            raise ShareOperationError(share_id=share_id, error=error)

        logger.debug("%s share %s finished: %s", action_name, share_id, result)
        if 'error' in result:
            raise ShareOperationError(share_id=share_id, error=result['error'])
Exemplo n.º 10
0
 def initWithDelegate_(self, delegate):
     self = super(U1FinderLib, self).init()
     self.sync_daemon_tool = SyncDaemonTool(None)
     self.delegate = delegate
     cfreactor.install()
     return self
Exemplo n.º 11
0
class U1FinderLib(NSObject):
    
    ##
    # Default constructor.
    @objc.typedSelector('@@:@')
    def initWithDelegate_(self, delegate):
        self = super(U1FinderLib, self).init()
        self.sync_daemon_tool = SyncDaemonTool(None)
        self.delegate = delegate
        cfreactor.install()
        return self
    
    ##
    # Returns the list of the shared volumes in a NSArray<NSString>. Example:
    #
    # [
    #    @"/Users/jose/Ubuntu One",
    #    @"/Users/jose/Pictures"
    # ]
    @objc.typedSelector('v@:')
    def volumeList(self):
        d = self.sync_daemon_tool.get_folders()
        d.addCallback(lambda r: volume_list(r, self.delegate))
        return None

    ##
    # Returns a NSArray<NSString> whit all the files that are being uploaded. Example:
    # [
    #     @"/Users/jose/Ubuntu One/Document.pdf",
    #     @"/Users/jose/Pictures/Image.png"
    # }
    @objc.typedSelector('v@:')
    def currentUploads(self):
        d = self.sync_daemon_tool.get_current_uploads()
        d.addCallback(lambda r: get_uploads(r, self.delegate))
        return None

    ##
    # Like currentUploads() but with the downloads.
    @objc.typedSelector('v@:')
    def currentDownloads(self):
        d = self.sync_daemon_tool.get_current_downloads()
        d.addCallback(lambda r: get_downloads(r, self.delegate))
        return None
    
    ##
    # Indicates if the specified file is public or not.
    @objc.typedSelector('@@:@')
    def isFilePublic_(self, filePath):
        d = self.sync_daemon_tool.get_public_files()
        d.addCallback(lambda r: file_is_public(r, filePath, self.delegate))
        return None
    
    ##
    # Publish or unpublish the specified file.
    @objc.typedSelector('v@:@B')
    def changeFile_visibillity_(self, filePath, isPublic):
        self.sync_daemon_tool.change_public_access(os.path.abspath(filePath), isPublic)
        return None

    ##
    # Returns the link (NSString) of a public file or nil if the file is not public.
    @objc.typedSelector('@@:@')
    def getPublicLinkOfFile_(self, filePath):
        d = self.sync_daemon_tool.get_public_files()
        d.addCallback(lambda r: get_public_files(r, filePath, self.delegate))
        return None

    ##
    # Synchronizes the specified folder
    @objc.typedSelector('@@:@')
    def synchronizeFolderAtPath_(self, folderPath):
        d = self.sync_daemon_tool.create_folder(os.path.abspath(folderPath))
        d.addCallback(lambda r: folder_synchronized(r, self.delegate))
        return None

    ##
    # Unsuscribes the specified folder.
    @objc.typedSelector('@@:@')
    def unsuscribeFolderAtPath_(self, folderPath):
        d = self.sync_daemon_tool.get_folders()
        d.addCallback(lambda r: unsuscribe_volume_list(r, folderPath, self.sync_daemon_tool, self.delegate))
        return None
	def __init__(self):
		print "init"
		self.sd = SyncDaemonTool()

		self.detect_shares()