def syncDeck(self, deck=None): try: if deck: # multi-mode setup sqlpath = deck.encode("utf-8") c = sqlite.connect(sqlpath) (syncName, localMod, localSync) = c.execute( "select syncName, modified, lastSync from decks").fetchone() c.close() if not syncName: return -2 syncName = os.path.splitext(os.path.basename(deck))[0] path = deck else: syncName = self.parent.syncName path = self.parent.deckPath sqlpath = path.encode("utf-8") c = sqlite.connect(sqlpath) (localMod, localSync) = c.execute( "select modified, lastSync from decks").fetchone() c.close() except Exception, e: # we don't know which db library we're using, so do string match if "locked" in unicode(e): return # unknown error self.error(e) return -1
def _fullup(self, wrapper, infile, version): wrapper.close() path = wrapper.path # DRS: most of this function was graciously copied # from anki.sync.SyncTools.fullSyncFromServer() (fd, tmpname) = tempfile.mkstemp(dir=os.getcwd(), prefix="fullsync") outfile = open(tmpname, 'wb') decomp = zlib.decompressobj() while 1: data = infile.read(CHUNK_SIZE) if not data: outfile.write(decomp.flush()) break outfile.write(decomp.decompress(data)) infile.close() outfile.close() os.close(fd) # if we were successful, overwrite old deck if os.path.exists(path): os.unlink(path) os.rename(tmpname, path) # reset the deck name c = sqlite.connect(path) lastSync = time.time() if version == '1': c.execute("update decks set lastSync = ?", [lastSync]) elif version == '2': c.execute("update decks set syncName = ?, lastSync = ?", [checksum(path.encode("utf-8")), lastSync]) c.commit() c.close() return lastSync
def setupForSync(wrapper): wrapper.close() c = sqlite.connect(d) lastSync = time.time() c.execute("update decks set lastSync = ?", [lastSync]) c.commit() c.close()
def fullSyncFromServer(self, fields, path): try: runHook("fullSyncStarted", 0) fields = urllib.urlencode(fields) src = urllib.urlopen(SYNC_URL + "fulldown", fields) (fd, tmpname) = tempfile.mkstemp(dir=os.path.dirname(path), prefix="fullsync") tmp = open(tmpname, "wb") decomp = zlib.decompressobj() cnt = 0 while 1: data = src.read(CHUNK_SIZE) if not data: tmp.write(decomp.flush()) break tmp.write(decomp.decompress(data)) cnt += CHUNK_SIZE runHook("fullSyncProgress", "fromServer", cnt) src.close() tmp.close() os.close(fd) # if we were successful, overwrite old deck os.unlink(path) os.rename(tmpname, path) # reset the deck name c = sqlite.connect(path) c.execute("update decks set syncName = ?", [checksum(path.encode("utf-8"))]) c.commit() c.close() finally: runHook("fullSyncFinished")
def fullSyncFromLocal(self, fields, path): global sendProgressHook try: # write into a temporary file, since POST needs content-length src = open(path, "rb") (fd, name) = tempfile.mkstemp(prefix="anki") tmp = open(name, "w+b") # post vars for (key, value) in fields.items(): tmp.write('--' + MIME_BOUNDARY + "\r\n") tmp.write('Content-Disposition: form-data; name="%s"\r\n' % key) tmp.write('\r\n') tmp.write(value) tmp.write('\r\n') # file header tmp.write('--' + MIME_BOUNDARY + "\r\n") tmp.write( 'Content-Disposition: form-data; name="deck"; filename="deck"\r\n' ) tmp.write('Content-Type: application/octet-stream\r\n') tmp.write('\r\n') # data comp = zlib.compressobj() while 1: data = src.read(CHUNK_SIZE) if not data: tmp.write(comp.flush()) break tmp.write(comp.compress(data)) src.close() tmp.write('\r\n--' + MIME_BOUNDARY + '--\r\n\r\n') size = tmp.tell() tmp.seek(0) # open http connection runHook("fullSyncStarted", size) headers = { 'Content-type': 'multipart/form-data; boundary=%s' % MIME_BOUNDARY, 'Content-length': str(size), 'Host': SYNC_HOST, } req = urllib2.Request(SYNC_URL + "fullup?v=2", tmp, headers) try: sendProgressHook = fullSyncProgressHook res = urllib2.urlopen(req).read() assert res.startswith("OK") # update lastSync c = sqlite.connect(path) c.execute("update decks set lastSync = ?", (res[3:], )) c.commit() c.close() finally: sendProgressHook = None tmp.close() os.close(fd) os.unlink(name) finally: runHook("fullSyncFinished")
def fullSyncFromLocal(self, fields, path): global sendProgressHook try: # write into a temporary file, since POST needs content-length src = open(path, "rb") (fd, name) = tempfile.mkstemp(prefix="anki") tmp = open(name, "w+b") # post vars for (key, value) in fields.items(): tmp.write('--' + MIME_BOUNDARY + "\r\n") tmp.write('Content-Disposition: form-data; name="%s"\r\n' % key) tmp.write('\r\n') tmp.write(value) tmp.write('\r\n') # file header tmp.write('--' + MIME_BOUNDARY + "\r\n") tmp.write( 'Content-Disposition: form-data; name="deck"; filename="deck"\r\n') tmp.write('Content-Type: application/octet-stream\r\n') tmp.write('\r\n') # data comp = zlib.compressobj() while 1: data = src.read(CHUNK_SIZE) if not data: tmp.write(comp.flush()) break tmp.write(comp.compress(data)) src.close() tmp.write('\r\n--' + MIME_BOUNDARY + '--\r\n\r\n') size = tmp.tell() tmp.seek(0) # open http connection runHook("fullSyncStarted", size) headers = { 'Content-type': 'multipart/form-data; boundary=%s' % MIME_BOUNDARY, 'Content-length': str(size), 'Host': SYNC_HOST, } req = urllib2.Request(SYNC_URL + "fullup?v=2", tmp, headers) try: sendProgressHook = fullSyncProgressHook res = urllib2.urlopen(req).read() assert res.startswith("OK") # update lastSync c = sqlite.connect(path) c.execute("update decks set lastSync = ?", (res[3:],)) c.commit() c.close() finally: sendProgressHook = None tmp.close() os.close(fd) os.unlink(name) finally: runHook("fullSyncFinished")
def syncDeck(self, deck=None): try: if deck: # multi-mode setup c = sqlite.connect(deck) (syncName, localMod, localSync) = c.execute( "select syncName, modified, lastSync from decks").fetchone() c.close() if not syncName: return path = deck else: syncName = self.parent.syncName path = self.parent.deckPath c = sqlite.connect(path) (localMod, localSync) = c.execute( "select modified, lastSync from decks").fetchone() c.close() except Exception, e: # we don't know which db library we're using, so do string match if "locked" in unicode(e): return # unknown error raise
def onSyncFinished(self): "Reopen after sync finished." self.form.buttonStack.show() try: try: if not self.showBrowser: # no deck load & no deck browser, as we're about to quit or do # something manually pass else: if self.loadAfterSync == -1: # after sync all, so refresh browser list self.browserLastRefreshed = 0 self.moveToState("deckBrowser") elif self.loadAfterSync and self.deckPath: if self.loadAfterSync == 2: name = re.sub("[<>]", "", self.syncName) p = os.path.join(self.config['documentDir'], name + ".anki") shutil.copy2(self.deckPath, p) self.deckPath = p # since we've moved the deck, we have to set sync path # ourselves c = sqlite.connect(p) v = c.execute( "select version from decks").fetchone()[0] if v >= 52: # deck has bene upgraded already, so we can # use a checksum name = checksum(p.encode("utf-8")) else: # FIXME: compat code because deck hasn't been # upgraded yet. can be deleted in the future. # strip off .anki part name = os.path.splitext(os.path.basename(p))[0] c.execute("update decks set syncName = ?", (name, )) c.commit() c.close() self.loadDeck(self.deckPath) else: self.moveToState("deckBrowser") except: self.moveToState("deckBrowser") raise finally: self.deckPath = None self.syncFinished = True
def onSyncFinished(self): "Reopen after sync finished." self.form.buttonStack.show() try: try: if not self.showBrowser: # no deck load & no deck browser, as we're about to quit or do # something manually pass else: if self.loadAfterSync == -1: # after sync all, so refresh browser list self.browserLastRefreshed = 0 self.moveToState("deckBrowser") elif self.loadAfterSync and self.deckPath: if self.loadAfterSync == 2: name = re.sub("[<>]", "", self.syncName) p = os.path.join(self.config['documentDir'], name + ".anki") shutil.copy2(self.deckPath, p) self.deckPath = p # since we've moved the deck, we have to set sync path # ourselves c = sqlite.connect(p) v = c.execute( "select version from decks").fetchone()[0] if v >= 52: # deck has bene upgraded already, so we can # use a checksum name = checksum(p.encode("utf-8")) else: # FIXME: compat code because deck hasn't been # upgraded yet. can be deleted in the future. # strip off .anki part name = os.path.splitext( os.path.basename(p))[0] c.execute("update decks set syncName = ?", (name,)) c.commit() c.close() self.loadDeck(self.deckPath) else: self.moveToState("deckBrowser") except: self.moveToState("deckBrowser") raise finally: self.deckPath = None self.syncFinished = True
if self.conflictResolution == "keepLocal": client.remoteTime = 0 elif self.conflictResolution == "keepRemote" or self.onlyMerge: client.localTime = 0 lastSync = self.deck.lastSync ret = client.prepareFullSync() if ret[0] == "fromLocal": if not self.conflictResolution: if lastSync <= 0 and not deckCreated: self.clobberChoice = None self.emit(SIGNAL("syncClobber"), syncName) while not self.clobberChoice: time.sleep(0.2) if self.clobberChoice == "cancel": # disable syncing on this deck c = sqlite.connect(sqlpath) c.execute( "update decks set syncName = null, " "lastSync = 0") c.commit() c.close() if not deck: # alert we're finished early self.emit(SIGNAL("syncFinished")) return True self.setStatus(_("Uploading..."), 0) client.fullSyncFromLocal(ret[1], ret[2]) else: self.setStatus(_("Downloading..."), 0) client.fullSyncFromServer(ret[1], ret[2]) self.setStatus(_("Sync complete."), 0)