diff --git a/oml/api.py b/oml/api.py index 514bd51..c9bb492 100644 --- a/oml/api.py +++ b/oml/api.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # vi:si:et:sw=4:sts=4:ts=4 +from __future__ import division import item.api import user.api - diff --git a/oml/changelog.py b/oml/changelog.py index e6e0679..eecaba0 100644 --- a/oml/changelog.py +++ b/oml/changelog.py @@ -59,14 +59,16 @@ class Changelog(db.Model): @classmethod def apply_changes(cls, user, changes): for change in changes: - if not Changelog.apply_change(user, change): + if not Changelog.apply_change(user, change, trigger=False): print 'FAIL', change break return False + if changes: + trigger_event('change', {}); return True @classmethod - def apply_change(cls, user, change, rebuild=False): + def apply_change(cls, user, change, rebuild=False, trigger=True): revision, timestamp, sig, data = change last = Changelog.query.filter_by(user_id=user.id).order_by('-revision').first() next_revision = last.revision + 1 if last else 0 @@ -87,6 +89,8 @@ class Changelog(db.Model): print 'change applied' db.session.add(c) db.session.commit() + if trigger: + trigger_event('change', {}); return True else: print 'INVLAID SIGNATURE ON CHANGE', change diff --git a/oml/directory.py b/oml/directory.py index 731925b..47eb3c6 100644 --- a/oml/directory.py +++ b/oml/directory.py @@ -36,7 +36,7 @@ def put(sk, data): 'X-Ed25519-Signature': sig } try: - r = requests.put(url, data, headers=headers) + r = requests.put(url, data, headers=headers, timeout=2) except: import traceback print 'directory.put failed:', data diff --git a/oml/item/api.py b/oml/item/api.py index 9f43121..b51d6ad 100644 --- a/oml/item/api.py +++ b/oml/item/api.py @@ -2,9 +2,7 @@ # vi:si:et:sw=4:sts=4:ts=4 from __future__ import division -from datetime import datetime - -from flask import json +import json from oxflask.api import actions from oxflask.shortcuts import returns_json @@ -12,8 +10,6 @@ import query import models import settings -from changelog import Changelog -import re import state import meta @@ -35,14 +31,16 @@ def find(request): qs = models.Find.query.filter_by(key=q['group']) if items: qs = qs.filter(models.Find.item_id.in_(items)) - for f in qs.values('value', 'findvalue'): - value = f[0] - findvalue = f[1] - if findvalue not in groups: - groups[findvalue] = 0 - groups[findvalue] += 1 - names[findvalue] = value - g = [{'name': names[k], 'items': groups[k]} for k in groups] + for f in qs.values('value', 'findvalue'): + value = f[0] + findvalue = f[1] + if findvalue not in groups: + groups[findvalue] = 0 + groups[findvalue] += 1 + names[findvalue] = value + g = [{'name': names[k], 'items': groups[k]} for k in groups] + else: + g = [] if 'sort' in q: g.sort(key=lambda k: k[q['sort'][0]['key']]) if q['sort'][0]['operator'] == '-': diff --git a/oml/item/query.py b/oml/item/query.py index 164f1b6..70d587f 100644 --- a/oml/item/query.py +++ b/oml/item/query.py @@ -19,14 +19,6 @@ def parse(data): query[key] = data[key] #print data query['qs'] = oxflask.query.Parser(models.Item).find(data) - if 'query' in query and 'conditions' in query['query'] and query['query']['conditions']: - conditions = query['query']['conditions'] - condition = conditions[0] - if condition['key'] == '*': - value = condition['value'].lower() - query['qs'] = models.Item.query.join( - models.Find, models.Find.item_id==models.Item.id).filter( - models.Find.value.contains(value)) if not 'group' in query: query['qs'] = order(query['qs'], query['sort']) return query diff --git a/oml/item/scan.py b/oml/item/scan.py index 0d76ec5..094ba0a 100644 --- a/oml/item/scan.py +++ b/oml/item/scan.py @@ -18,6 +18,7 @@ from changelog import Changelog import media from websocket import trigger_event +import state extensions = ['epub', 'pdf', 'txt'] @@ -62,9 +63,6 @@ def run_scan(): if ext in extensions: books.append(f) - trigger_event('scan', { - 'progress': [0, len(books)], - }) position = 0 added = 0 for f in ox.sorted_strings(books): @@ -95,33 +93,25 @@ def run_scan(): item.added = datetime.now() item.scrape() added += 1 - trigger_event('scan', { - 'added': added, - 'progress': [position, len(books)], - 'path': path, - }) - trigger_event('scan', { - 'progress': [position, len(books)], - 'added': added, - 'status': {'code': 200, 'text': ''} - }) + trigger_event('change', {}) def run_import(options=None): options = options or {} with app.app_context(): prefs = settings.preferences - prefix = options.get('path', os.path.expanduser(prefs['importPath'])) - prefix_books = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/') - prefix_imported = os.path.join(prefix_books, 'Imported/') + prefix = os.path.expanduser(options.get('path', prefs['importPath'])) if not prefix[-1] == '/': prefix += '/' - + prefix_books = os.path.join(os.path.expanduser(prefs['libraryPath']), 'Books/') + prefix_imported = os.path.join(prefix_books, 'Imported/') if not os.path.exists(prefix): - trigger_event('import', { + trigger_event('activity', { + 'activity': 'import', 'progress': [0, 0], 'status': {'code': 404, 'text': 'path not found'} }) + state.activity = {} user = User.get_or_create(settings.USER_ID) listname = options.get('list') if listname: @@ -138,13 +128,17 @@ def run_import(options=None): if ext in extensions: books.append(f) - trigger_event('import', { + state.activity = { + 'activity': 'import', 'progress': [0, len(books)], - }) + } + trigger_event('activity', state.activity) position = 0 added = 0 for f in ox.sorted_strings(books): position += 1 + if not os.path.exists(f): + continue id = media.get_id(f) file = File.get(id) path = f[len(prefix):] @@ -180,16 +174,20 @@ def run_import(options=None): if listname: listitems.append(item.id) added += 1 - trigger_event('import', { + state.activity = { + 'activity': 'import', 'progress': [position, len(books)], 'path': path, 'added': added, - }) + } + trigger_event('activity', state.activity) if listname: l = List.get_or_create(settings.USER_ID, listname) l.add_items(listitems) - trigger_event('import', { + trigger_event('activity', { + 'activity': 'import', 'progress': [position, len(books)], 'status': {'code': 200, 'text': ''}, 'added': added, }) + state.activity = {} diff --git a/oml/item/views.py b/oml/item/views.py index e8ea91b..fb12aa1 100644 --- a/oml/item/views.py +++ b/oml/item/views.py @@ -2,7 +2,6 @@ # vi:si:et:sw=4:sts=4:ts=4 from __future__ import division -import os from datetime import datetime import zipfile import mimetypes @@ -10,7 +9,7 @@ from StringIO import StringIO import Image from flask import Blueprint -from flask import json, request, make_response, abort, send_file +from flask import make_response, abort, send_file from covers import covers import settings diff --git a/oml/localnodes.py b/oml/localnodes.py index 67044f8..50d7602 100644 --- a/oml/localnodes.py +++ b/oml/localnodes.py @@ -29,7 +29,7 @@ def can_connect(data): def get_interface(): interface = '' if sys.platform == 'darwin': - #cmd = ['netstat', '-rn'] + #cmd = ['/usr/sbin/netstat', '-rn'] cmd = ['/sbin/route', '-n', 'get', 'default'] p = subprocess.Popen(cmd, stdout=subprocess.PIPE) stdout, stderr = p.communicate() @@ -92,7 +92,8 @@ class LocalNodes(Thread): data = data[:-1] # Strip trailing \0's data = self.verify(data) if data: - print addr + #fixme use local link address + #print addr if data['id'] != USER_ID: if data['id'] not in self._nodes: thread.start_new_thread(self.new_node, (data, )) diff --git a/oml/node/api.py b/oml/node/api.py index c5ccab4..47cdd39 100644 --- a/oml/node/api.py +++ b/oml/node/api.py @@ -1,3 +1,7 @@ +# -*- coding: utf-8 -*- +# vi:si:et:sw=4:sts=4:ts=4 +from __future__ import division + import settings from changelog import Changelog from user.models import User diff --git a/oml/node/server.py b/oml/node/server.py index 793aec7..d4a1b34 100644 --- a/oml/node/server.py +++ b/oml/node/server.py @@ -2,12 +2,9 @@ # vi:si:et:sw=4:sts=4:ts=4 import os -import sys import tornado -from tornado.web import StaticFileHandler, Application, FallbackHandler -from tornado.wsgi import WSGIContainer +from tornado.web import Application from tornado.httpserver import HTTPServer -from tornado.ioloop import IOLoop, PeriodicCallback import settings @@ -104,23 +101,26 @@ class ShareHandler(tornado.web.RequestHandler): self.finish() -def start(app): - application = tornado.web.Application([ - (r"/get/(.*)", ShareHandler, dict(app=app)), - (r".*", NodeHandler, dict(app=app)), - ]) - if not os.path.exists(settings.ssl_cert_path): - settings.server['cert'] = cert.generate_ssl() - - http_server = tornado.httpserver.HTTPServer(application, ssl_options={ - "certfile": settings.ssl_cert_path, - "keyfile": settings.ssl_key_path - }) - http_server.listen(settings.server['node_port'], settings.server['node_address']) +def publish_node(): host = utils.get_public_ipv6() state.online = directory.put(settings.sk, { 'host': host, 'port': settings.server['node_port'], 'cert': settings.server['cert'] }) + +def start(app): + application = Application([ + (r"/get/(.*)", ShareHandler, dict(app=app)), + (r".*", NodeHandler, dict(app=app)), + ]) + if not os.path.exists(settings.ssl_cert_path): + settings.server['cert'] = cert.generate_ssl() + + http_server = HTTPServer(application, ssl_options={ + "certfile": settings.ssl_cert_path, + "keyfile": settings.ssl_key_path + }) + http_server.listen(settings.server['node_port'], settings.server['node_address']) + state.main.add_callback(publish_node) return http_server diff --git a/oml/node/utils.py b/oml/node/utils.py index c9d5e1b..f099404 100644 --- a/oml/node/utils.py +++ b/oml/node/utils.py @@ -11,10 +11,3 @@ def get_public_ipv6(): s.close() return ip -def get_public_ipv4(): - host = ('10.0.3.1', 25519) - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(host) - ip = s.getsockname()[0] - s.close() - return ip diff --git a/oml/oxflask/api.py b/oml/oxflask/api.py index cccb1be..dd690cf 100644 --- a/oml/oxflask/api.py +++ b/oml/oxflask/api.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # vi:si:et:sw=4:sts=4:ts=4 from __future__ import division, with_statement + import inspect import sys import json diff --git a/oml/server.py b/oml/server.py index d38dafa..c3f9d1a 100644 --- a/oml/server.py +++ b/oml/server.py @@ -19,8 +19,6 @@ def run(): root_dir = os.path.normpath(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..')) PID = sys.argv[2] if len(sys.argv) > 2 else None - state.main = IOLoop.instance() - static_path = os.path.join(root_dir, 'static') options = { @@ -37,11 +35,15 @@ def run(): ] http_server = HTTPServer(Application(handlers, **options)) + http_server.listen(settings.server['port'], settings.server['address']) + if PID: with open(PID, 'w') as pid: pid.write('%s' % os.getpid()) + state.main = IOLoop.instance() + def start_node(): import user import downloads diff --git a/oml/state.py b/oml/state.py index aad36e3..493ba48 100644 --- a/oml/state.py +++ b/oml/state.py @@ -3,6 +3,8 @@ nodes = False main = None online = False +activity = {} + def user(): import settings import user.models diff --git a/oml/user/api.py b/oml/user/api.py index bd5d138..ae54b5a 100644 --- a/oml/user/api.py +++ b/oml/user/api.py @@ -1,15 +1,16 @@ # -*- coding: utf-8 -*- # vi:si:et:sw=4:sts=4:ts=4 +from __future__ import division import os from copy import deepcopy +import subprocess +import json -from flask import json from oxflask.api import actions from oxflask.shortcuts import returns_json import models -from item.models import Item from utils import get_position_by_id @@ -176,6 +177,9 @@ actions.register(editUser, cache=False) @returns_json def requestPeering(request): data = json.loads(request.form['data']) if 'data' in request.form else {} + if len(data.get('id', '')) != 43: + print 'invalid user id' + return {} p = models.User.get_or_create(data['id']) state.nodes.queue('add', p.id) state.nodes.queue(p.id, 'requestPeering', data.get('message', '')) @@ -185,6 +189,9 @@ actions.register(requestPeering, cache=False) @returns_json def acceptPeering(request): data = json.loads(request.form['data']) if 'data' in request.form else {} + if len(data.get('id', '')) != 43: + print 'invalid user id' + return {} p = models.User.get_or_create(data['id']) state.nodes.queue('add', p.id) state.nodes.queue(p.id, 'acceptPeering', data.get('message', '')) @@ -194,6 +201,9 @@ actions.register(acceptPeering, cache=False) @returns_json def rejectPeering(request): data = json.loads(request.form['data']) if 'data' in request.form else {} + if len(data.get('id', '')) != 43: + print 'invalid user id' + return {} p = models.User.get_or_create(data['id']) state.nodes.queue('add', p.id) state.nodes.queue(p.id, 'rejectPeering', data.get('message', '')) @@ -203,6 +213,9 @@ actions.register(rejectPeering, cache=False) @returns_json def removePeering(request): data = json.loads(request.form['data']) if 'data' in request.form else {} + if len(data.get('id', '')) != 43: + print 'invalid user id' + return {} u = models.User.get_or_create(data['id']) state.nodes.queue('add', u.id) state.nodes.queue(u.id, 'removePeering', data.get('message', '')) @@ -212,8 +225,40 @@ actions.register(removePeering, cache=False) @returns_json def cancelPeering(request): data = json.loads(request.form['data']) if 'data' in request.form else {} + if len(data.get('id', '')) != 43: + print 'invalid user id' + return {} p = models.User.get_or_create(data['id']) state.nodes.queue('add', p.id) state.nodes.queue(p.id, 'cancelPeering', data.get('message', '')) return {} actions.register(cancelPeering, cache=False) + +@returns_json +def getActivity(request): + return state.activity +actions.register(getActivity, cache=False) + +@returns_json +def selectFolder(request): + data = json.loads(request.form['data']) if 'data' in request.form else {} + cmd = ['./ctl', 'ui', 'folder'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + path = stdout.decode('utf-8').strip() + return { + 'path': path + } +actions.register(selectFolder, cache=False) + +@returns_json +def selectFile(request): + data = json.loads(request.form['data']) if 'data' in request.form else {} + cmd = ['./ctl', 'ui', 'file'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + path = stdout.decode('utf-8').strip() + return { + 'path': path + } +actions.register(selectFile, cache=False) diff --git a/oml/websocket.py b/oml/websocket.py index dff2831..e6d5423 100644 --- a/oml/websocket.py +++ b/oml/websocket.py @@ -5,9 +5,6 @@ from __future__ import division from tornado.websocket import WebSocketHandler from tornado.ioloop import IOLoop from Queue import Queue -import urllib2 -import os -from contextlib import closing import json from threading import Thread @@ -19,9 +16,9 @@ class Background: def __init__(self, handler): self.handler = handler - self.main = IOLoop.instance() self.q = Queue() self.connected = True + self.main = IOLoop.instance() def worker(self): while self.connected: