mirror of
https://github.com/ankitects/anki.git
synced 2025-11-07 21:27:14 -05:00
move common auth+upload code into base class
This commit is contained in:
parent
bf3bb9dd32
commit
a8d2578be5
1 changed files with 74 additions and 63 deletions
171
anki/sync.py
171
anki/sync.py
|
|
@ -389,30 +389,12 @@ class LocalServer(Syncer):
|
||||||
l = simplejson.loads; d = simplejson.dumps
|
l = simplejson.loads; d = simplejson.dumps
|
||||||
return l(d(Syncer.applyChanges(self, minUsn, lnewer, l(d(changes)))))
|
return l(d(Syncer.applyChanges(self, minUsn, lnewer, l(d(changes)))))
|
||||||
|
|
||||||
# Syncing over HTTP
|
# HTTP syncing tools
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
class RemoteServer(Syncer):
|
class HttpSyncer(object):
|
||||||
def __init__(self, user, hkey):
|
|
||||||
self.user = user
|
|
||||||
self.hkey = hkey
|
|
||||||
self.con = None
|
|
||||||
|
|
||||||
def meta(self):
|
|
||||||
h = httplib2.Http(timeout=60)
|
|
||||||
resp, cont = h.request(
|
|
||||||
SYNC_URL+"meta?" + urllib.urlencode(dict(u=self.user,v=SYNC_VER)))
|
|
||||||
# fixme: convert these into easily-catchable errors
|
|
||||||
if resp['status'] in ('503', '504'):
|
|
||||||
raise Exception("Server is too busy; please try again later.")
|
|
||||||
elif resp['status'] == '501':
|
|
||||||
raise Exception("Your client is out of date; please upgrade.")
|
|
||||||
elif resp['status'] == '403':
|
|
||||||
raise Exception("Invalid key; please authenticate.")
|
|
||||||
elif resp['status'] != '200':
|
|
||||||
raise Exception("Invalid response code: %s" % resp['status'])
|
|
||||||
return simplejson.loads(cont)
|
|
||||||
|
|
||||||
|
# retrieving a host key for future operations
|
||||||
def hostKey(self, pw):
|
def hostKey(self, pw):
|
||||||
h = httplib2.Http(timeout=60)
|
h = httplib2.Http(timeout=60)
|
||||||
resp, cont = h.request(
|
resp, cont = h.request(
|
||||||
|
|
@ -422,71 +404,13 @@ class RemoteServer(Syncer):
|
||||||
self.hkey = cont
|
self.hkey = cont
|
||||||
return cont
|
return cont
|
||||||
|
|
||||||
def applyChanges(self, **kw):
|
|
||||||
self.con = httplib2.Http(timeout=60)
|
|
||||||
return self._run("applyChanges", kw)
|
|
||||||
|
|
||||||
def chunk(self, **kw):
|
|
||||||
return self._run("chunk", kw)
|
|
||||||
|
|
||||||
def applyChunk(self, **kw):
|
|
||||||
return self._run("applyChunk", kw)
|
|
||||||
|
|
||||||
def sanityCheck(self, **kw):
|
|
||||||
return self._run("sanityCheck", kw)
|
|
||||||
|
|
||||||
def finish(self, **kw):
|
|
||||||
return self._run("finish", kw)
|
|
||||||
|
|
||||||
def _vars(self):
|
|
||||||
return dict(k=self.hkey)
|
|
||||||
|
|
||||||
def _run(self, cmd, data):
|
|
||||||
return simplejson.loads(
|
|
||||||
postData(self.con, cmd, StringIO(simplejson.dumps(data)),
|
|
||||||
self._vars()))
|
|
||||||
|
|
||||||
# Full syncing
|
|
||||||
##########################################################################
|
|
||||||
|
|
||||||
class FullSyncer(object):
|
|
||||||
|
|
||||||
def __init__(self, deck, hkey):
|
|
||||||
self.deck = deck
|
|
||||||
self.hkey = hkey
|
|
||||||
|
|
||||||
def _vars(self):
|
|
||||||
return dict(k=self.hkey)
|
|
||||||
|
|
||||||
def _con(self):
|
|
||||||
return httplib2.Http(timeout=60)
|
|
||||||
|
|
||||||
def download(self):
|
|
||||||
self.deck.close()
|
|
||||||
resp, cont = self._con().request(
|
|
||||||
SYNC_URL+"download?" + urllib.urlencode(self._vars()))
|
|
||||||
if resp['status'] != '200':
|
|
||||||
raise Exception("Invalid response code: %s" % resp['status'])
|
|
||||||
tpath = self.deck.path + ".tmp"
|
|
||||||
open(tpath, "wb").write(cont)
|
|
||||||
os.unlink(self.deck.path)
|
|
||||||
os.rename(tpath, self.deck.path)
|
|
||||||
d = DB(self.deck.path)
|
|
||||||
assert d.scalar("pragma integrity_check") == "ok"
|
|
||||||
self.deck = None
|
|
||||||
|
|
||||||
def upload(self):
|
|
||||||
self.deck.beforeUpload()
|
|
||||||
assert postData(self._con(), "upload", open(self.deck.path, "rb"),
|
|
||||||
self._vars(), comp=6) == "OK"
|
|
||||||
|
|
||||||
# Posting data as a file
|
# Posting data as a file
|
||||||
######################################################################
|
######################################################################
|
||||||
# We don't want to post the payload as a form var, as the percent-encoding is
|
# We don't want to post the payload as a form var, as the percent-encoding is
|
||||||
# costly. We could send it as a raw post, but more HTTP clients seem to
|
# costly. We could send it as a raw post, but more HTTP clients seem to
|
||||||
# support file uploading, so this is the more compatible choice.
|
# support file uploading, so this is the more compatible choice.
|
||||||
|
|
||||||
def postData(http, method, fobj, vars, comp=1):
|
def postData(self, http, method, fobj, vars, comp=1):
|
||||||
bdry = "--"+MIME_BOUNDARY
|
bdry = "--"+MIME_BOUNDARY
|
||||||
# write out post vars, including session key and compression flag
|
# write out post vars, including session key and compression flag
|
||||||
buf = StringIO()
|
buf = StringIO()
|
||||||
|
|
@ -528,3 +452,90 @@ Content-Type: application/octet-stream\r\n\r\n""")
|
||||||
if resp['status'] != '200':
|
if resp['status'] != '200':
|
||||||
raise Exception("Invalid response code: %s" % resp['status'])
|
raise Exception("Invalid response code: %s" % resp['status'])
|
||||||
return cont
|
return cont
|
||||||
|
|
||||||
|
class RemoteServer(Syncer, HttpSyncer):
|
||||||
|
def __init__(self, user, hkey):
|
||||||
|
self.user = user
|
||||||
|
self.hkey = hkey
|
||||||
|
self.con = None
|
||||||
|
|
||||||
|
def meta(self):
|
||||||
|
h = httplib2.Http(timeout=60)
|
||||||
|
resp, cont = h.request(
|
||||||
|
SYNC_URL+"meta?" + urllib.urlencode(dict(u=self.user,v=SYNC_VER)))
|
||||||
|
# fixme: convert these into easily-catchable errors
|
||||||
|
if resp['status'] in ('503', '504'):
|
||||||
|
raise Exception("Server is too busy; please try again later.")
|
||||||
|
elif resp['status'] == '501':
|
||||||
|
raise Exception("Your client is out of date; please upgrade.")
|
||||||
|
elif resp['status'] == '403':
|
||||||
|
raise Exception("Invalid key; please authenticate.")
|
||||||
|
elif resp['status'] != '200':
|
||||||
|
raise Exception("Invalid response code: %s" % resp['status'])
|
||||||
|
return simplejson.loads(cont)
|
||||||
|
|
||||||
|
def applyChanges(self, **kw):
|
||||||
|
self.con = httplib2.Http(timeout=60)
|
||||||
|
return self._run("applyChanges", kw)
|
||||||
|
|
||||||
|
def chunk(self, **kw):
|
||||||
|
return self._run("chunk", kw)
|
||||||
|
|
||||||
|
def applyChunk(self, **kw):
|
||||||
|
return self._run("applyChunk", kw)
|
||||||
|
|
||||||
|
def sanityCheck(self, **kw):
|
||||||
|
return self._run("sanityCheck", kw)
|
||||||
|
|
||||||
|
def finish(self, **kw):
|
||||||
|
return self._run("finish", kw)
|
||||||
|
|
||||||
|
def _vars(self):
|
||||||
|
return dict(k=self.hkey)
|
||||||
|
|
||||||
|
def _run(self, cmd, data):
|
||||||
|
return simplejson.loads(
|
||||||
|
self.postData(self.con, cmd, StringIO(simplejson.dumps(data)),
|
||||||
|
self._vars()))
|
||||||
|
|
||||||
|
# Full syncing
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
class FullSyncer(HttpSyncer):
|
||||||
|
|
||||||
|
def __init__(self, deck, hkey):
|
||||||
|
self.deck = deck
|
||||||
|
self.hkey = hkey
|
||||||
|
|
||||||
|
def _vars(self):
|
||||||
|
return dict(k=self.hkey)
|
||||||
|
|
||||||
|
def _con(self):
|
||||||
|
return httplib2.Http(timeout=60)
|
||||||
|
|
||||||
|
def download(self):
|
||||||
|
self.deck.close()
|
||||||
|
resp, cont = self._con().request(
|
||||||
|
SYNC_URL+"download?" + urllib.urlencode(self._vars()))
|
||||||
|
if resp['status'] != '200':
|
||||||
|
raise Exception("Invalid response code: %s" % resp['status'])
|
||||||
|
tpath = self.deck.path + ".tmp"
|
||||||
|
open(tpath, "wb").write(cont)
|
||||||
|
os.unlink(self.deck.path)
|
||||||
|
os.rename(tpath, self.deck.path)
|
||||||
|
d = DB(self.deck.path)
|
||||||
|
assert d.scalar("pragma integrity_check") == "ok"
|
||||||
|
self.deck = None
|
||||||
|
|
||||||
|
def upload(self):
|
||||||
|
self.deck.beforeUpload()
|
||||||
|
assert self.postData(self._con(), "upload", open(self.deck.path, "rb"),
|
||||||
|
self._vars(), comp=6) == "OK"
|
||||||
|
|
||||||
|
# Media syncing
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
class MediaSyncer(HttpSyncer):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue