Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 117 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,117 @@
*~
*.pyc
/.coverage
/AnkiServer.egg-info
/development.ini
/server.log
/collections
/session.db
/auth.db
/dist
/build
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
test/
downloads/
eggs/
.eggs/
bin/
lib/
lib64/
include/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
*.txt
*.doc
101.py
Pipfile
Pipfile.lock
*.jpg
*.gif
img
auth.db
files.txt
16 changes: 9 additions & 7 deletions AnkiServer/apps/rest_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ def add_handler(self, type, name, handler):
- 'handler' is a callable that takes (collection, data, ids).
"""

if self.handlers[type].has_key(name):
raise "Handler already for %(type)s/%(name)s exists!"
#if self.handlers[type].has_key(name):
if name in self.handlers[type]:
raise #"Handler already for %(type)s/%(name)s exists!"
self.handlers[type][name] = handler

def add_handler_group(self, type, group):
Expand Down Expand Up @@ -248,7 +249,7 @@ def _parseRequestBody(self, req):

try:
data = json.loads(req.body)
except JSONDecodeError, e:
except JSONDecodeError as e:
logging.error(req.path+': Unable to parse JSON: '+str(e), exc_info=True)
raise HTTPBadRequest()

Expand Down Expand Up @@ -285,7 +286,7 @@ def __call__(self, req):

# get the collection path
collection_path = self._getCollectionPath(ids[0])
print collection_path
print(collection_path)

# get the handler function
handler, hasReturnValue = self._getHandler(type, name)
Expand All @@ -308,10 +309,10 @@ def __call__(self, req):
col = self.collection_manager.get_collection(collection_path, self.setup_new_collection)
handler_request = RestHandlerRequest(self, data, ids, session)
output = col.execute(self._execute_handler, [handler_request, handler], {}, hasReturnValue)
except HTTPError, e:
except HTTPError as e:
# we pass these on through!
raise
except Exception, e:
except Exception as e:
logging.error(e)
return HTTPInternalServerError()

Expand Down Expand Up @@ -355,7 +356,8 @@ def latest_notes(self, col, req):
# TODO: use SQLAlchemy objects to do this
sql = "SELECT n.id FROM notes AS n";
args = []
if req.data.has_key('updated_since'):
if 'updated_since' in req.data:
#if req.data.has_key('updated_since'):
sql += ' WHERE n.mod > ?'
args.append(req.data['updated_since'])
sql += ' ORDER BY n.mod DESC'
Expand Down
46 changes: 24 additions & 22 deletions AnkiServer/apps/sync_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from webob import Response

import os
import io
import hashlib
import logging
import random
Expand All @@ -35,20 +36,14 @@
from anki.utils import intTime, checksum, isMac
from anki.consts import SYNC_ZIP_SIZE, SYNC_ZIP_COUNT

logging.basicConfig(filename='server.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s',level=logging.DEBUG)

try:
import simplejson as json
except ImportError:
import json

try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

try:
from pysqlite2 import dbapi2 as sqlite
except ImportError:
from sqlite3 import dbapi2 as sqlite
from sqlite3 import dbapi2 as sqlite

class SyncCollectionHandler(Syncer):
operations = ['meta', 'applyChanges', 'start', 'chunk', 'applyChunk', 'sanityCheck2', 'finish']
Expand Down Expand Up @@ -130,7 +125,7 @@ def _check_zip_data(zip_data):
max_zip_size = 100*1024*1024
max_meta_file_size = 100000

file_buffer = StringIO(zip_data)
file_buffer = io.BytesIO(zip_data)
zip_file = zipfile.ZipFile(file_buffer, 'r')

meta_file_size = zip_file.getinfo("_meta").file_size
Expand All @@ -152,7 +147,7 @@ def _adopt_media_changes_from_zip(self, zip_data):
according to the data in zip file zipData.
"""

file_buffer = StringIO(zip_data)
file_buffer = io.BytesIO(zip_data)
zip_file = zipfile.ZipFile(file_buffer, 'r')

# Get meta info first.
Expand Down Expand Up @@ -241,7 +236,7 @@ def downloadFiles(self, files):
flist = {}
cnt = 0
sz = 0
f = StringIO()
f = io.BytesIO()
z = zipfile.ZipFile(f, "w", compression=zipfile.ZIP_DEFLATED)

for fname in files:
Expand Down Expand Up @@ -436,7 +431,7 @@ def _decode_data(self, data, compression=0):
import gzip

if compression:
buf = gzip.GzipFile(mode="rb", fileobj=StringIO(data))
buf = gzip.GzipFile(mode="rb", fileobj=io.BytesIO(data))
data = buf.read()
buf.close()

Expand Down Expand Up @@ -562,12 +557,12 @@ def __call__(self, req):
if url in SyncCollectionHandler.operations + SyncMediaHandler.operations:
# 'meta' passes the SYNC_VER but it isn't used in the handler
if url == 'meta':
if session.skey == None and req.POST.has_key('s'):
if session.skey == None and 's' in req.POST:
session.skey = req.POST['s']
if data.has_key('v'):
if 'v' in data:
session.version = data['v']
del data['v']
if data.has_key('cv'):
if 'cv' in data:
session.client_version = data['cv']
self.session_manager.save(hkey, session)
session = self.session_manager.load(hkey, self.create_session)
Expand Down Expand Up @@ -752,17 +747,24 @@ def authenticate(self, username, password):
salt = db_hash[-16:]
hashobj = hashlib.sha256()

hashobj.update(username+password+salt)
hashobj.update((username+password+salt).encode())

conn.close()
loggin.info(db_ret,db_hash)

passhash = hashobj.hexdigest() + salt

if passhash == db_hash:
return True
else:
return False

return (db_ret != None and hashobj.hexdigest()+salt == db_hash)

# Our entry point
def make_app(global_conf, **local_conf):
if local_conf.has_key('session_db_path'):
if 'session_db_path' in local_conf:
local_conf['session_manager'] = SqliteSessionManager(local_conf['session_db_path'])
if local_conf.has_key('auth_db_path'):
if 'auth_db_path' in local_conf:
local_conf['user_manager'] = SqliteUserManager(local_conf['auth_db_path'])
return SyncApp(**local_conf)

Expand All @@ -773,10 +775,10 @@ def main():
ankiserver = SyncApp()
httpd = make_server('', 8001, ankiserver)
try:
print "Starting..."
print( "Starting...")
httpd.serve_forever()
except KeyboardInterrupt:
print "Exiting ..."
print( "Exiting ...")
finally:
shutdown()

Expand Down
2 changes: 1 addition & 1 deletion AnkiServer/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def __create_collection(self):
dirname = os.path.dirname(self.path)
try:
os.makedirs(dirname)
except OSError, exc:
except OSError as exc:
if exc.errno == errno.EEXIST:
pass
else:
Expand Down
6 changes: 3 additions & 3 deletions AnkiServer/threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from AnkiServer.collection import CollectionWrapper, CollectionManager

from threading import Thread
from Queue import Queue
from queue import Queue

import time, logging

Expand Down Expand Up @@ -93,15 +93,15 @@ def _run(self):

try:
ret = self.wrapper.execute(func, args, kw, return_queue)
except Exception, e:
except Exception as e:
logging.error('CollectionThread[%s]: Unable to %s(*%s, **%s): %s',
self.path, func_name, repr(args), repr(kw), e, exc_info=True)
# we return the Exception which will be raise'd on the other end
ret = e

if return_queue is not None:
return_queue.put(ret)
except Exception, e:
except Exception as e:
logging.error('CollectionThread[%s]: Thread crashed! Exception: %s', self.path, e, exc_info=True)
finally:
self.wrapper.close()
Expand Down
Loading