diff --git a/VERSION b/VERSION index 56b36e8a..eb3d111a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 1.99.7 (2012-03-12 10:41:17) dev +Version 1.99.7 (2012-03-12 12:07:09) dev diff --git a/applications/admin/controllers/webservices.py b/applications/admin/controllers/webservices.py new file mode 100644 index 00000000..cd220a3d --- /dev/null +++ b/applications/admin/controllers/webservices.py @@ -0,0 +1,140 @@ +from gluon.admin import * +from gluon.fileutils import abspath, read_file, write_file +from gluon.tools import Service +from glob import glob +import shutil +import platform +import time +import base64 +import os +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + + +service = Service(globals()) + + +@service.jsonrpc +def login(): + "dummy function to test credentials" + return True + + +@service.jsonrpc +def list_apps(): + "list installed applications" + regex = re.compile('^\w+$') + apps = [f for f in os.listdir(apath(r=request)) if regex.match(f)] + return apps + + +@service.jsonrpc +def list_files(app, pattern='.*\.py$'): + files = listdir(apath('%s/' % app, r=request), pattern) + return [x.replace('\\','/') for x in files] + + +@service.jsonrpc +def read_file(filename, b64=False): + """ Visualize object code """ + f = open(apath(filename, r=request), "rb") + try: + data = f.read() + if not b64: + data = data.replace('\r','') + else: + data = base64.b64encode(data) + finally: + f.close() + return data + + +@service.jsonrpc +def write_file(filename, data, b64=False): + f = open(apath(filename, r=request), "wb") + try: + if not b64: + data = data.replace('\r\n', '\n').strip() + '\n' + else: + data = base64.b64decode(data) + f.write(data) + finally: + f.close() + + +@service.jsonrpc +def hash_file(filename): + data = read_file(filename) + file_hash = md5_hash(data) + path = apath(filename, r=request) + saved_on = os.stat(path)[stat.ST_MTIME] + size = os.path.getsize(path) + return dict(saved_on=saved_on, file_hash=file_hash, size=size) + + +@service.jsonrpc +def install(app_name, filename, data, overwrite=True): + f = StringIO(base64.b64decode(data)) + installed = app_install(app_name, f, request, filename, + overwrite=overwrite) + + return installed + +@service.jsonrpc +def attach_debugger(host='localhost', port=6000, authkey='secret password'): + import gluon.contrib.qdb as qdb + import gluon.debug + from multiprocessing.connection import Listener + + if isinstance(authkey, unicode): + authkey = authkey.encode('utf8') + + if not hasattr(gluon.debug, 'qdb_listener'): + # create a remote debugger server and wait for connection + address = (host, port) # family is deduced to be 'AF_INET' + gluon.debug.qdb_listener = Listener(address, authkey=authkey) + gluon.debug.qdb_connection = gluon.debug.qdb_listener.accept() + # create the backend + gluon.debug.qdb_debugger = qdb.Qdb(gluon.debug.qdb_connection) + gluon.debug.dbg = gluon.debug.qdb_debugger + # welcome message (this should be displayed on the frontend) + print 'debugger connected to', gluon.debug.qdb_listener.last_accepted + return True # connection successful! + + +@service.jsonrpc +def detach_debugger(): + import gluon.contrib.qdb as qdb + import gluon.debug + # stop current debugger + if gluon.debug.qdb_debugger: + try: + gluon.debug.qdb_debugger.do_quit() + except: + pass + if hasattr(gluon.debug, 'qdb_listener'): + if gluon.debug.qdb_connection: + gluon.debug.qdb_connection.close() + del gluon.debug.qdb_connection + if gluon.debug.qdb_listener: + gluon.debug.qdb_listener.close() + del gluon.debug.qdb_listener + gluon.debug.qdb_debugger = None + return True + +def call(): + "Entry point. Prevents access to action if not admin password is present" + + basic = request.env.http_authorization + if not basic or not basic[:6].lower() == 'basic ': + raise HTTP(401,"Wrong credentials") + (username, password) = base64.b64decode(basic[6:]).split(':') + if not verify_password(password) or not is_manager(): + time.sleep(10) + raise HTTP(403,"Not authorized") + + session.forget() + return service() +