Esempio n. 1
0
    def _upload_photo(self, uploadInfo):
        """
        Import a file into the f-spot catalog
        """
        # Check if remote is read only
        if self.photo_remote.IsReadOnly():
            raise Exceptions.SyncronizeError(
                _("F-Spot DBus interface is operating in read-only mode"))

        # create roll if necessary
        if not self.has_roll:
            self.prepare_roll()

        # start with enabled tags from gui, they exist in fspot for sure
        tags = list(self.enabledTags)

        # add tags from upload info
        for tag in uploadInfo.tags:
            self._create_tag(tag)
            tags.append(tag)

        # import the photo
        try:
            id = self.photo_remote.ImportPhoto(uploadInfo.url, True, tags)
            return Rid(uid=str(id))
        except:
            raise Exceptions.SynchronizeError('Import Failed')
Esempio n. 2
0
    def run(self):
        """
        The main refresh state machine.
        
        Takes the conduit through the init->is_configured->refresh
        steps, setting its status at the appropriate time and performing
        nicely in the case of errors. 
        """
        log.debug("Started thread %s (thread: %s)" %
                  (self, thread.get_ident()))
        try:
            log.debug("Refresh %s beginning" % self)
            self.cond.emit("sync-started")

            if not self.dataproviderWrapper.module.is_configured(
                    isSource=self.cond.get_dataprovider_position(
                        self.dataproviderWrapper)[0] == 0,
                    isTwoWay=self.cond.is_two_way()):
                self.dataproviderWrapper.module.set_status(
                    DataProvider.STATUS_DONE_SYNC_NOT_CONFIGURED)
                #Cannot continue if source not configured
                raise Exceptions.StopSync(self.state)

            self.state = self.REFRESH_STATE
            try:
                self.dataproviderWrapper.module.refresh()
                self.dataproviderWrapper.module.set_status(
                    DataProvider.STATUS_DONE_REFRESH_OK)
            except Exceptions.RefreshError:
                self.dataproviderWrapper.module.set_status(
                    DataProvider.STATUS_DONE_REFRESH_ERROR)
                log.warn("RefreshError: %s" % self.dataproviderWrapper)
                #Cannot continue with no source data
                raise Exceptions.StopSync(self.state)
            except Exception:
                self.dataproviderWrapper.module.set_status(
                    DataProvider.STATUS_DONE_REFRESH_ERROR)
                log.critical(
                    "UNKNOWN REFRESH ERROR: %s\n%s" %
                    (self.dataproviderWrapper, traceback.format_exc()))
                #Cannot continue with no source data
                raise Exceptions.StopSync(self.state)

        except Exceptions.StopSync:
            log.warn("Sync Aborted")
            self.aborted = True

        conduit.GLOBALS.mappingDB.save()
        self.cond.emit("sync-completed", self.aborted, self.did_sync_error(),
                       self.did_sync_conflict())
Esempio n. 3
0
 def put(self, data, overwrite, LUID=None):
     DataProvider.DataSink.put(self, data, overwrite, LUID)
     if self.slow:
         time.sleep(1)
     if self.count >= self.errorAfter:
         if self.errorFatal:
             raise Exceptions.SyncronizeFatalError(
                 "Error After:%s Count:%s" % (self.errorAfter, self.count))
         else:
             raise Exceptions.SyncronizeError("Error After:%s Count:%s" %
                                              (self.errorAfter, self.count))
     self.count += 1
     newData = TestDataType(data.get_UID())
     return newData.get_rid()
Esempio n. 4
0
 def put(self, data, overwrite, LUID=None):
     DataProvider.DataSink.put(self, data, overwrite, LUID)
     newData = TestDataType(data.get_UID())
     if not overwrite:
         raise Exceptions.SynchronizeConflictError(
             conduit.datatypes.COMPARISON_UNKNOWN, data, newData)
     return newData.get_rid()
Esempio n. 5
0
    def put(self, data, overwrite, LUID):
        """
        @returns: The Rid of the page at location LUID
        """
        DataProvider.TwoWay.put(self, data, overwrite, LUID)
        #If LUID is None, then we have once-upon-a-time uploaded this data
        if LUID != None:
            #Check if the remote data exists (i.e. has it been deleted)
            if self._data_exists(LUID):
                #The remote page exists
                if overwrite == False:
                    #Only replace the data if it is newer than the remote one
                    oldData = self._get_data(LUID)
                    comp = data.compare(oldData)
                    if comp == conduit.datatypes.COMPARISON_NEWER:
                        return self._replace_data(LUID, data)
                    elif comp == conduit.datatypes.COMPARISON_EQUAL:
                        #We are the same, so return either rid
                        return oldData.get_rid()
                    else:
                        #If we are older that the remote page, or if the two could not
                        #be compared, then we must ask the user what to do via a conflict
                        raise Exceptions.SynchronizeConflictError(
                            comp, data, oldData)

        #If we get here then the data is new
        return self._put_data(data)
Esempio n. 6
0
    def refresh(self):
        DataProvider.DataSource.refresh(self)
        #only work if Banshee is installed
        if not os.path.exists(BansheeSource.MUSIC_DB):
            raise Exceptions.RefreshError("Banshee is not installed")

        #Stupid pysqlite thread stuff.
        #Connection must be made in the same thread
        #as any execute statements
        con = sqlite.connect(BansheeSource.MUSIC_DB)
        cur = con.cursor()

        for playlistid in self.playlists:
            if BANSHEE_VERSION_1:
                cur.execute(
                    "select Uri from CoreTracks INNER JOIN CorePlaylistEntries ON CorePlaylistEntries.TrackID=CoreTracks.TrackID where PlaylistID=%s"
                    % (playlistid))
            else:
                cur.execute(
                    "select Uri from Tracks INNER JOIN PlaylistEntries ON PlaylistEntries.TrackID=Tracks.TrackID where PlaylistID=%s"
                    % (playlistid))
            for Uri in cur:
                self.tracks.append(self._get_full_uri(Uri[0]))

        for playlistid in self.smart_playlists + self.video_playlists:
            cur.execute(
                "select Uri from CoreTracks INNER JOIN CoreSmartPlaylistEntries ON CoreSmartPlaylistEntries.TrackID where PlaylistID=%s"
                % (playlistid))
            for Uri in cur:
                self.tracks.append(self._get_full_uri(Uri[0]))
        con.close()
Esempio n. 7
0
    def put(self, localfile, overwrite, LUID):
        """
        Stores the given File object remotely on Amazon S3, if certain
        conditions are met.
        @returns: The Rid of the page at location LUID.
        """
        DataProvider.TwoWay.put(self, localfile, overwrite, LUID)
        # If LUID is None, then we have once-upon-a-time uploaded this file
        if LUID != None:
            # Check if the remote file exists (i.e. has it been deleted)
            if self._data_exists(LUID):
                # The remote file exists
                if not overwrite:
                    # Only replace the data if it is newer than the remote one
                    remotefile = self._get_data(LUID)
                    comp = localfile.compare(remotefile)
                    if comp == conduit.datatypes.COMPARISON_NEWER:
                        return self._replace_data(LUID, localfile)
                    elif comp == conduit.datatypes.COMPARISON_EQUAL:
                        # We are the same, so return either rid
                        return remotefile.get_rid()
                    else:
                        # If we are older than the remote page, or if the two
                        # could not be compared, then we must ask the user what
                        # to do via a conflict
                        raise Exceptions.SynchronizeConflictError(
                            comp, localfile, remotefile)

        # If we get here then the file is new
        return self._put_data(localfile)
Esempio n. 8
0
 def refresh(self):
     Image.ImageTwoWay.refresh(self)
     self.photos = []
     if self._connect_to_fspot():
         self.photos = self.photo_remote.Query(self.enabledTags)
     else:
         raise Exceptions.RefreshError("FSpot not available")
Esempio n. 9
0
 def refresh(self):
     DataProvider.TwoWay.refresh(self)
     self.notes = []
     if self._connect_to_tomboy():
         self.notes = [str(i) for i in self.remoteTomboy.ListAllNotes()]
     else:
         raise Exceptions.RefreshError("Tomboy not available")
Esempio n. 10
0
    def put(self, note, overwrite, LUID=None):
        """
        Stores a Note in Tomboy.
        """
        DataProvider.TwoWay.put(self, note, overwrite, LUID)
        log.debug("Put note LUID: %s" % LUID)

        #Check if the note, or one with same title exists
        existingNote = None
        if LUID != None:
            if self.remoteTomboy.NoteExists(LUID):
                existingNote = self._get_note(LUID)
        else:
            LUID = self.remoteTomboy.FindNote(note.get_title())
            if LUID != "":
                existingNote = self._get_note(str(LUID))

        #compare with the existing note
        if existingNote != None:
            comp = note.compare(existingNote)
            log.debug("Comparing new %s with existing %s" %
                      (note.get_title(), existingNote.get_title()))
            if comp == conduit.datatypes.COMPARISON_EQUAL:
                log.info("Notes are equal")
            elif overwrite == True or comp == conduit.datatypes.COMPARISON_NEWER:
                log.info("Updating note")
                self._update_note(LUID, note)
            else:
                raise Exceptions.SynchronizeConflictError(
                    comp, note, existingNote)
        else:
            log.info("Saving new Note")
            LUID = self._create_note(note)

        return self.get(LUID).get_rid()
Esempio n. 11
0
    def put(self, obj, overwrite, LUID=None):
        DataProvider.TwoWay.put(self, obj, overwrite, LUID)
        if LUID != None:
            existing = self._get_object(LUID)
            if existing != None:
                if overwrite == True:
                    rid = self._update_object(LUID, obj)
                    return rid
                else:
                    comp = obj.compare(
                        existing,
                        "%s-%s" % (self.__class__.__name__, self.get_UID()))
                    # only update if newer
                    if comp != conduit.datatypes.COMPARISON_NEWER:
                        raise Exceptions.SynchronizeConflictError(
                            comp, obj, existing)
                    else:
                        # overwrite and return new ID
                        rid = self._update_object(LUID, obj)
                        return rid

        # if we get here then it is new...
        log.info("Creating new object")
        rid = self._create_object(obj)
        return rid
Esempio n. 12
0
 def _update_object(self, uid, obj):
     if self._delete_object(uid):
         uid = self._create_object(obj)
         return uid
     else:
         raise Exceptions.SyncronizeError(
             "Error updating object (uid: %s)" % uid)
Esempio n. 13
0
 def refresh(self):
     d = File.File(URI=self.folder)
     if not d.exists():
         try:
             d.make_directory_and_parents()
         except:
             raise Exceptions.RefreshError("Error Creating Directory")
     FileDataProvider.FolderTwoWay.refresh(self)
Esempio n. 14
0
 def _upload_photo(self, uploadInfo):
     """
     Upload to album
     """
     try:
         fotoId = self.zapi.add_to_album(uploadInfo, self.albumId)
     except Exception, e:
         raise Exceptions.SyncronizeError("Zoto Upload Error.")
Esempio n. 15
0
 def _replace_photo(self, id, uploadInfo):
     """
     Updates a photo (binary and metadata)
     """
     try:
         fotoId = self.zapi.update_photo(id, uploadInfo)
     except Exception, e:
         raise Exceptions.SyncronizeError("Zoto Update Error.")
Esempio n. 16
0
    def put(self, photo, overwrite, LUID=None):
        """
        Accepts a vfs file. Must be made local.
        I also store a md5 of the photos uri to check for duplicates
        """
        DataProvider.DataSink.put(self, photo, overwrite, LUID)

        originalName = photo.get_filename()
        #Gets the local URI (/foo/bar). If this is a remote file then
        #it is first transferred to the local filesystem
        photoURI = photo.get_local_uri()
        mimeType = photo.get_mimetype()
        tags = photo.get_tags()
        caption = photo.get_caption()

        uploadInfo = UploadInfo(photoURI, mimeType, originalName, tags,
                                caption)

        if overwrite and LUID:
            rid = self._replace_photo(LUID, uploadInfo)
        else:
            if LUID and self._get_photo_info(LUID):
                remotePhoto = self.get(LUID)
                comp = photo.compare(remotePhoto, False)
                log.debug(
                    "Compared %s with %s. Result = %s" %
                    (photo.get_filename(), remotePhoto.get_filename(), comp))

                if LUID != None and comp == conduit.datatypes.COMPARISON_NEWER:
                    rid = self._replace_photo(LUID, uploadInfo)
                elif comp == conduit.datatypes.COMPARISON_EQUAL:
                    rid = remotePhoto.get_rid()
                else:
                    raise Exceptions.SynchronizeConflictError(
                        comp, photo, remotePhoto)
            else:
                log.debug(
                    "Uploading Photo URI = %s, Mimetype = %s, Original Name = %s"
                    % (photoURI, mimeType, originalName))
                rid = self._upload_photo(uploadInfo)

        if not rid:
            raise Exceptions.SyncronizeError("Error putting/updating photo")
        else:
            return rid
Esempio n. 17
0
    def _upload_photo(self, uploadInfo):
        """
		Upload to album
		"""
        try:
            ret = self.salbum.uploadPhoto(uploadInfo.url, uploadInfo.mimeType,
                                          uploadInfo.name)
            return Rid(ret.id)
        except Exception, e:
            raise Exceptions.SyncronizeError("Shutterfly Upload Error.")
Esempio n. 18
0
    def _update_note(self, uid, note):
        log.debug("Updating note uid: %s" % uid)
        if note.get_xml() != None:
            ok = self.remoteTomboy.SetNoteCompleteXml(uid, note.get_xml())
        else:
            ok = self.remoteTomboy.SetNoteContents(uid, note.get_contents())

        if not ok:
            raise Exceptions.SyncronizeError(
                "Error setting Tomboy note content (uri: %s)" % uid)
Esempio n. 19
0
 def check_thread_not_cancelled(self, dataprovidersToCancel):
     """
     Checks if the thread has been scheduled to be cancelled. If it has
     then this function sets the status of the dataproviders to indicate
     that they were stopped through a cancel operation.
     """
     if self.cancelled:
         for s in dataprovidersToCancel:
             s.module.set_status(DataProvider.STATUS_DONE_SYNC_CANCELLED)
         raise Exceptions.StopSync(self.state)
Esempio n. 20
0
    def get(self, LUID):
        try:
            DataProvider.DataSource.get(self, LUID)
            songuri = str(self.dbus.GetTrackInfo(LUID, 'location'))
            f = RhythmboxAudio(URI=songuri)
            f.set_UID(LUID)
            f.set_open_URI(songuri)

            return f
        except DBusClosedConnectionError:
            raise Exceptions.SyncronizeFatalError()
Esempio n. 21
0
    def _get_all_albums(self):
        #only work if picasa has been configured to use a CSV DB
        #http://www.zmarties.com/picasa/
        dbfile = os.path.join(PICASA_DIR, 'drive_c', 'Program Files',
                              'Picasa2', 'db', 'dirscanner.csv')
        if not os.path.exists(dbfile):
            raise Exceptions.RefreshError(
                "Picasa Not Configured to use CSV Database")

        pals = []
        #Open the CSV file and find all entries with Type = 19 (albums)
        f = open(dbfile, 'rt')
        try:
            reader = csv.DictReader(f)
            for row in reader:
                if row['Type'] == '19':
                    #wine picasa stores all pal files (that describes an album)
                    #in the following base dir
                    parts = [
                        PICASA_DIR, 'drive_c', 'Documents and Settings',
                        os.getlogin(), 'Local Settings'
                    ]
                    #and then as given in the csv file
                    #but first change the windows path to a linux one
                    parts += row['Name'].split("\\")
                    path = os.path.abspath(os.sep.join(parts))
                    pals.append(path)
        finally:
            f.close()

        #parse each pal file to get album info
        albums = []
        for pal in pals:
            log.debug("Parsing album file %s" % pal)
            doc = xml.dom.minidom.parse(pal)
            #album name
            for prop in doc.getElementsByTagName('property'):
                if prop.hasAttribute("name") and prop.getAttribute(
                        "name") == "name":
                    name = prop.getAttribute("value")
            #image filenames
            photos = []
            for f in doc.getElementsByTagName('filename'):
                filename = self._fix_picasa_image_filename(f.firstChild.data)
                if filename != None:
                    photos.append(filename)

            albums.append((
                pal,  #FILENAME_IDX
                name,  #DISPLAYNAME_IDX 
                photos))  #PHOTOS_IDX

        return albums
Esempio n. 22
0
 def _upload_photo(self, uploadInfo):
     """
     Upload to album; and return image id here
     """
     try:
         rsp = self.fapi.photos.upload(uploadInfo.url,
                                       aid=self.albums.get(
                                           self.albumname, None))
         pid = str(rsp["pid"])
         return Rid(uid=pid)
     except pyfacebook.FacebookError, f:
         raise Exceptions.SyncronizeError("Facebook Upload Error %s" % f)
Esempio n. 23
0
 def get(self, LUID):
     for title in self._notes:
         uid, timestamp, content = self._notes[title]
         if uid == LUID:
             n = Note.Note(
                 title=title,
                 #FIXME: Backpack doesnt have mtime, only creation time
                 modified=datetime.datetime.fromtimestamp(timestamp),
                 contents=content)
             n.set_UID(LUID)
             return n
     raise Exceptions.SyncronizeError("Could not find note %s" % LUID)
Esempio n. 24
0
def marshal_fault_to_exception(fault, **kwargs):
    if fault.faultCode in XML_RPC_EASY_EXCEPTIONS:
        klass = getattr(Exceptions, fault.faultCode)
        #exception.message = fault.faultString
        raise klass(fault.faultString)
    elif fault.faultCode == "SynchronizeConflictError":
        fromData = kwargs['server'].get(kwargs['fromDataLUID'])
        toData = kwargs['toData']
        raise Exceptions.SynchronizeConflictError(fault.faultString, fromData,
                                                  toData)
    else:
        raise Exception("Remote Exception:\n%s" % fault.faultString)
Esempio n. 25
0
 def get_all(self):
     DataProvider.DataSource.get_all(self)
     try:
         # LUID is now a Rhythmbox ID, that only makes sense to Rhythmbox
         songs = []
         #only consider enabled playlists
         for playlist in [
                 p for p in self.allPlaylists if p in self.playlists
         ]:
             for song in self.dbus.GetPlaylistTracks(playlist):
                 songs.append(str(song))
         return songs
     except DBusClosedConnectionError:
         raise Exceptions.SyncronizeFatalError()
Esempio n. 26
0
    def delete(self, LUID):
        """
        Delete a photo by ID
        """
        if not self.sphotos.has_key(LUID):
            log.warn("Photo does not exist")
            return

        try:
            self.zapi.delete_from_album(LUID, self.albumId)
            del self.sphotos[LUID]
        except xmlrpclib.Fault, e:
            raise Exceptions.SyncronizeError("Zoto Delete Error: " +
                                             e.faultString)
Esempio n. 27
0
    def _create_object(self, note):
        obj = evolution.ecal.ECalComponent(
            evolution.ecal.CAL_COMPONENT_JOURNAL)
        obj.set_summary(note.title)
        if note.contents != None:
            obj.set_description(note.contents)
        uid = self.memos.add_object(obj)

        if uid != None:
            mtime = datetime.datetime.fromtimestamp(obj.get_modified())
            note = self._get_object(uid)
            return note.get_rid()
        else:
            raise Exceptions.SyncronizeError("Error creating memo")
Esempio n. 28
0
    def _create_object(self, event):
        # work around.. (avoid duplicate UIDs)
        if "UID" in [x.name for x in list(event.iCal.lines())]:
            event.iCal.remove(event.iCal.uid)

        obj = evolution.ecal.ECalComponent(evolution.ecal.CAL_COMPONENT_TODO,
                                           event.get_ical_string())
        if self.tasks.add_object(obj):
            mtime = datetime.datetime.fromtimestamp(obj.get_modified())
            return conduit.datatypes.Rid(uid=obj.get_uid(),
                                         mtime=mtime,
                                         hash=mtime)
        else:
            raise Exceptions.SyncronizeError("Error creating event")
Esempio n. 29
0
    def put(self, photo, overwrite, LUID=None):
        """
        Accepts a vfs file. Must be made local.
        I also store a md5 of the photos uri to check for duplicates
        """
        DataProvider.DataSink.put(self, photo, overwrite, LUID)

        originalName = photo.get_filename()
        #Gets the local URI (/foo/bar). If this is a remote file then
        #it is first transferred to the local filesystem
        photoURI = photo.get_local_uri()
        mimeType = photo.get_mimetype()
        tags = photo.get_tags()
        caption = photo.get_caption()

        uploadInfo = UploadInfo(photoURI, mimeType, originalName, tags,
                                caption)

        #Check if we have already uploaded the photo
        if LUID != None:
            info = self._get_photo_info(LUID)
            #check if a photo exists at that UID
            if info != None:
                if overwrite == True:
                    #replace the photo
                    return self._replace_photo(LUID, uploadInfo)
                else:
                    #Only upload the photo if it is newer than the Remote one
                    url = self._get_raw_photo_url(info)
                    remoteFile = File.File(url)

                    #this is a limited test for equality type comparison
                    comp = photo.compare(remoteFile, True)
                    log.debug(
                        "Compared %s with %s to check if they are the same (size). Result = %s"
                        % (photo.get_filename(), remoteFile.get_filename(),
                           comp))
                    if comp != conduit.datatypes.COMPARISON_EQUAL:
                        raise Exceptions.SynchronizeConflictError(
                            comp, photo, remoteFile)
                    else:
                        return conduit.datatypes.Rid(uid=LUID)

        log.debug(
            "Uploading Photo URI = %s, Mimetype = %s, Original Name = %s" %
            (photoURI, mimeType, originalName))

        #upload the file
        return self._upload_photo(uploadInfo)
Esempio n. 30
0
    def delete(self, LUID):
        """
		Delete a photo by ID
		Deleting a photo invalidates album length and photo index values.
		We must reload the photos (or do something else...)
		"""
        if not self.sphotos.has_key(LUID):
            log.warn("Photo does not exist")
            return

        try:
            self.salbum.deletePhoto(self.sphotos[LUID])
        except Exception, e:
            raise Exceptions.SyncronizeError(
                "Shutterfly Delete Error - Try Again.")