diff options
Diffstat (limited to 'module')
| -rw-r--r-- | module/web/ServerThread.py | 15 | ||||
| -rw-r--r-- | module/web/WebServer.py | 374 | ||||
| -rw-r--r-- | module/web/ajax/__init__.py (renamed from module/web/__init__.py) | 0 | ||||
| -rw-r--r-- | module/web/ajax/models.py | 3 | ||||
| -rw-r--r-- | module/web/ajax/tests.py | 23 | ||||
| -rw-r--r-- | module/web/ajax/urls.py | 0 | ||||
| -rw-r--r-- | module/web/ajax/views.py | 1 | ||||
| -rw-r--r-- | module/web/bottle.py | 1231 | ||||
| -rw-r--r-- | module/web/main.html | 29 | ||||
| -rw-r--r-- | module/web/main.js | 42 | ||||
| -rw-r--r-- | module/web/manage.py | 12 | ||||
| -rw-r--r-- | module/web/media/css/default.css | 145 | ||||
| -rw-r--r-- | module/web/media/css/window.css (renamed from module/web/static/window.css) | 0 | ||||
| -rw-r--r-- | module/web/media/img/Button-Add-grey.png (renamed from module/web/static/default/Button-Add-grey.png) | bin | 2112 -> 2112 bytes | |||
| -rw-r--r-- | module/web/media/img/Button-Add.png (renamed from module/web/static/default/Button-Add.png) | bin | 2110 -> 2110 bytes | |||
| -rw-r--r-- | module/web/media/img/Button-Pause-grey.png (renamed from module/web/static/default/Button-Pause-grey.png) | bin | 1932 -> 1932 bytes | |||
| -rw-r--r-- | module/web/media/img/Button-Pause.png (renamed from module/web/static/default/Button-Pause.png) | bin | 2146 -> 2146 bytes | |||
| -rw-r--r-- | module/web/media/img/Button-Play-grey.png (renamed from module/web/static/default/Button-Play-grey.png) | bin | 1938 -> 1938 bytes | |||
| -rw-r--r-- | module/web/media/img/Button-Play.png (renamed from module/web/static/default/Button-Play.png) | bin | 2023 -> 2023 bytes | |||
| -rw-r--r-- | module/web/media/img/big_button.gif (renamed from module/web/static/window/big_button.gif) | bin | 1905 -> 1905 bytes | |||
| -rw-r--r-- | module/web/media/img/big_button_over.gif (renamed from module/web/static/window/big_button_over.gif) | bin | 728 -> 728 bytes | |||
| -rw-r--r-- | module/web/media/img/body.png (renamed from module/web/static/window/body.png) | bin | 402 -> 402 bytes | |||
| -rw-r--r-- | module/web/media/img/closebtn.gif (renamed from module/web/static/window/closebtn.gif) | bin | 254 -> 254 bytes | |||
| -rw-r--r-- | module/web/media/img/drag_corner.gif (renamed from module/web/static/window/drag_corner.gif) | bin | 76 -> 76 bytes | |||
| -rw-r--r-- | module/web/media/img/full.png (renamed from module/web/static/window/full.png) | bin | 3543 -> 3543 bytes | |||
| -rw-r--r-- | module/web/media/img/head-login.png (renamed from module/web/static/default/head-login.png) | bin | 1288 -> 1288 bytes | |||
| -rw-r--r-- | module/web/media/img/head-menu-development.png (renamed from module/web/static/default/head-menu-development.png) | bin | 1324 -> 1324 bytes | |||
| -rw-r--r-- | module/web/media/img/head-menu-download.png (renamed from module/web/static/default/head-menu-download.png) | bin | 721 -> 721 bytes | |||
| -rw-r--r-- | module/web/media/img/head-menu-home.png (renamed from module/web/static/default/head-menu-home.png) | bin | 920 -> 920 bytes | |||
| -rw-r--r-- | module/web/media/img/head-menu-index.png (renamed from module/web/static/default/head-menu-index.png) | bin | 482 -> 482 bytes | |||
| -rw-r--r-- | module/web/media/img/head-menu-news.png (renamed from module/web/static/default/head-menu-news.png) | bin | 628 -> 628 bytes | |||
| -rw-r--r-- | module/web/media/img/head-menu-recent.png (renamed from module/web/static/default/head-menu-recent.png) | bin | 932 -> 932 bytes | |||
| -rw-r--r-- | module/web/media/img/head-menu-wiki.png (renamed from module/web/static/default/head-menu-wiki.png) | bin | 1204 -> 1204 bytes | |||
| -rw-r--r-- | module/web/media/img/head-search-noshadow.png (renamed from module/web/static/default/head-search-noshadow.png) | bin | 1187 -> 1187 bytes | |||
| -rw-r--r-- | module/web/media/img/head_bg1.png (renamed from module/web/static/default/head_bg1.png) | bin | 125 -> 125 bytes | |||
| -rw-r--r-- | module/web/media/img/page-tools-backlinks.png (renamed from module/web/static/default/page-tools-backlinks.png) | bin | 540 -> 540 bytes | |||
| -rw-r--r-- | module/web/media/img/page-tools-edit.png (renamed from module/web/static/default/page-tools-edit.png) | bin | 574 -> 574 bytes | |||
| -rw-r--r-- | module/web/media/img/page-tools-revisions.png (renamed from module/web/static/default/page-tools-revisions.png) | bin | 603 -> 603 bytes | |||
| -rw-r--r-- | module/web/media/img/progress-bar-back.gif (renamed from module/web/static/default/progress-bar-back.gif) | bin | 10819 -> 10819 bytes | |||
| -rw-r--r-- | module/web/media/img/progress-bar.gif (renamed from module/web/static/default/progress-bar.gif) | bin | 10819 -> 10819 bytes | |||
| -rw-r--r-- | module/web/media/img/pyload-logo-edited3.5-new-font-small.png (renamed from module/web/static/default/pyload-logo-edited3.5-new-font-small.png) | bin | 8457 -> 8457 bytes | |||
| -rw-r--r-- | module/web/media/img/tab-background.png (renamed from module/web/static/default/tab-background.png) | bin | 179 -> 179 bytes | |||
| -rw-r--r-- | module/web/media/img/tabs-border-bottom.png (renamed from module/web/static/default/tabs-border-bottom.png) | bin | 163 -> 163 bytes | |||
| -rw-r--r-- | module/web/media/img/user-actions-logout.png (renamed from module/web/static/default/user-actions-logout.png) | bin | 799 -> 799 bytes | |||
| -rw-r--r-- | module/web/media/img/user-actions-profile.png (renamed from module/web/static/default/user-actions-profile.png) | bin | 628 -> 628 bytes | |||
| -rw-r--r-- | module/web/media/js/home.js (renamed from module/web/static/default/home.js) | 0 | ||||
| -rw-r--r-- | module/web/media/js/mootools-1.2.3-core.js (renamed from module/web/static/mootools-1.2.3-core.js) | 0 | ||||
| -rw-r--r-- | module/web/media/js/mootools-1.2.3.1-more.js (renamed from module/web/static/mootools-1.2.3.1-more.js) | 0 | ||||
| -rw-r--r-- | module/web/media/js/status.js (renamed from module/web/static/default/status.js) | 0 | ||||
| -rw-r--r-- | module/web/pyload.db | bin | 0 -> 32768 bytes | |||
| -rw-r--r-- | module/web/pyload/__init__.py | 0 | ||||
| -rw-r--r-- | module/web/pyload/admin.py | 1 | ||||
| -rw-r--r-- | module/web/pyload/models.py | 21 | ||||
| -rw-r--r-- | module/web/pyload/tests.py | 23 | ||||
| -rw-r--r-- | module/web/pyload/urls.py | 7 | ||||
| -rw-r--r-- | module/web/pyload/views.py | 80 | ||||
| -rw-r--r-- | module/web/settings.py | 127 | ||||
| -rw-r--r-- | module/web/static/default.css | 189 | ||||
| -rw-r--r-- | module/web/static/favicon.ico | bin | 7206 -> 0 bytes | |||
| -rw-r--r-- | module/web/templates/default.tpl | 230 | ||||
| -rw-r--r-- | module/web/templates/default/base.html | 99 | ||||
| -rw-r--r-- | module/web/templates/default/downloads.html | 16 | ||||
| -rw-r--r-- | module/web/templates/default/home.html | 1 | ||||
| -rw-r--r-- | module/web/templates/default/login.html | 35 | ||||
| -rw-r--r-- | module/web/templates/default/logout.html | 9 | ||||
| -rw-r--r-- | module/web/templates/default/logs.html | 16 | ||||
| -rw-r--r-- | module/web/templates/default/queue.html | 16 | ||||
| -rw-r--r-- | module/web/templates/default/window.html (renamed from module/web/templates/window.tpl) | 0 | ||||
| -rw-r--r-- | module/web/templates/footer.tpl | 6 | ||||
| -rw-r--r-- | module/web/templates/header.tpl | 24 | ||||
| -rw-r--r-- | module/web/urls.py | 30 | 
71 files changed, 680 insertions, 2125 deletions
| diff --git a/module/web/ServerThread.py b/module/web/ServerThread.py new file mode 100644 index 000000000..803dc5dc5 --- /dev/null +++ b/module/web/ServerThread.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import threading +import os +from os.path import join + +class WebServer(threading.Thread): +    def __init__(self, pycore): +        threading.Thread.__init__(self) +        self.pycore = pycore +        self.setDaemon(True) +     +    def run(self): +        self.pycore.logger.info("Starting Webserver @ Port 8000") +        os.system("python " + join(self.pycore.path,"module","web","manage.py runserver")) +        #@TODO: really bad approach, better would be real python code, or subprocess
\ No newline at end of file diff --git a/module/web/WebServer.py b/module/web/WebServer.py deleted file mode 100644 index 15541676b..000000000 --- a/module/web/WebServer.py +++ /dev/null @@ -1,374 +0,0 @@ -#import sys -#from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -#from xmlrpclib import ServerProxy -#from time import time -#import re -# -#class Handler(BaseHTTPRequestHandler): -#     -#    def do_GET(self): -#        global coreserver -#        stdout = sys.stdout -#        sys.stdout = self.wfile -#        if self.path == "/": -#            print "Server Runs" -#        elif self.path == "/downloads": -#            print self.get_downloads() -#        elif re.search("/add=.?", self.path): -#            if re.match(is_url, self.path.split("/add=")[1]): -#                coreserver.add_urls([self.path.split("/add=")[1]]) -#                print "Link Added" -#        else: -#            try:  -#                print open(self.path[1:], 'r').read() -#            except IOError: -#                self.send_error(404) -#                 -#    def format_size(self, size): -#        return str(size / 1024) + " MiB" -# -#    def format_time(self,seconds): -#        seconds = int(seconds) -#        hours, seconds = divmod(seconds, 3600) -#        minutes, seconds = divmod(seconds, 60) -#        return "%.2i:%.2i:%.2i" % (hours, minutes, seconds) -#                 -#    def get_downloads(self): -#        data = coreserver.status_downloads() -#        for download in data: -#            print "<h3>%s</h3>" % download["name"] -#            if download["status"] == "downloading": -#                percent = download["percent"] -#                z = percent / 4 -#                print "<h3>%s</h3>" % dl_name -#                print "<font face='font-family:Fixedsys,Courier,monospace;'>[" + z * "#" + (25-z) * " " + "]</font>" + str(percent) + "%<br />" -#                print "Speed: " + str(int(download['speed'])) + " kb/s" -#                print "Size: " + self.format_size(download['size']) -#                print "Finished in: " + self.format_time(download['eta']) -#                print "ID: " + str(download['id']) -#                dl_status = "[" + z * "#" + (25-z) * " " + "] " + str(percent) + "%" + " Speed: " + str(int(download['speed'])) + " kb/s" + " Size: " + self.format_size(download['size']) + " Finished in: " + self.format_time(download['eta'])  + " ID: " + str(download['id']) -#            if download["status"] == "waiting": -#                print "waiting: " + self.format_time(download["wait_until"]- time()) -#                 -#is_url = re.compile("^(((https?|ftp)\:\/\/)?([\w\.\-]+(\:[\w\.\&%\$\-]+)*@)?((([^\s\(\)\<\>\\\"\.\[\]\,@;:]+)(\.[^\s\(\)\<\>\\\"\.\[\]\,@;:]+)*(\.[a-zA-Z]{2,4}))|((([01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}([01]?\d{1,2}|2[0-4]\d|25[0-5])))(\b\:(6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)\b)?((\/[^\/][\w\.\,\?\'\\\/\+&%\$#\=~_\-@]*)*[^\.\,\?\"\'\(\)\[\]!;<>{}\s\x7F-\xFF])?)$",re.IGNORECASE) -# -#coreserver = None -# -#class WebServer(): -# -#    def start(self): -#        try: -#            global coreserver -#            coreserver = ServerProxy("https://testuser:testpw@localhost:1337", allow_none=True) -#            webserver = HTTPServer(('',8080),Handler) -#            print 'server started at port 8080' -#            webserver.serve_forever() -#        except KeyboardInterrupt: -#            webserver.socket.close() -# -#if __name__ == "__main__": -#    web = WebServer() -#    web.start() - - -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -#Copyright (C) 2009 RaNaN -# -#This program is free software; you can redistribute it and/or modify -#it under the terms of the GNU General Public License as published by -#the Free Software Foundation; either version 3 of the License, -#or (at your option) any later version. -# -#This program is distributed in the hope that it will be useful, -#but WITHOUT ANY WARRANTY; without even the implied warranty of -#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -#See the GNU General Public License for more details. -# -#You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. -# -### -import random -import threading -import time - -import bottle -from bottle import abort -from bottle import redirect -from bottle import request -from bottle import response -from bottle import route -from bottle import run -from bottle import send_file -from bottle import template - - -core = None -core_methods = None - -PATH = "./module/web/" -TIME = time.strftime("%a, %d %b %Y 00:00:00 +0000", time.localtime()) #set time to current day -USERS = {} -# TODO: Implement new server methods -@route('/login', method='POST') -def do_login(): -    #print request.GET - - -    username = core.config['webinterface']['username'] -    pw = core.config['webinterface']['password'] - -    if request.POST['u'] == username and request.POST['p'] == pw: -         -        id = int(random.getrandbits(16)) -        ua = request.HEADER("HTTP_USER_AGENT") -        ip = request.HEADER("REMOTE_ADDR") - -        auth = {} - -        auth['ua'] = ua -        auth['ip'] = ip -        auth['user'] = username - -        USERS[id] = auth - -        response.COOKIES['user'] = username -        response.COOKIES['id'] = id - -        return template('default', page='loggedin', user=username) -    else: -        return template('default', page='login') - -@route('/login') -def login(): - -    if check_auth(request): -        redirect("/") - -    return template('default', page='login') - -@route('/logout') -def logout(): -    try: -        del USERS[int(request.COOKIES.get('id'))] -    except: -        pass -     -    redirect("/login") - -@route('/') -def home(): - -    if not check_auth(request): -        redirect("/login") - -    username = request.COOKIES.get('user') - -    dls = core_methods.status_downloads() - -    for dl in dls: -        dl['eta'] = str(core.format_time(dl['eta'])) -        dl['wait_until'] = str(core.format_time(dl['wait_until'] - time.time())) - -         -    return template('default', page='home', links=dls, user=username, status=core_methods.status_server()) - -@route('/queue') -def queue(): - -    if not check_auth(request): -        redirect("/login") - -    username = request.COOKIES.get('user') - -    return template('default', page='queue', links=core_methods.get_queue(), user=username, status=core_methods.status_server()) - -@route('/downloads') -def downloads(): - -    if not check_auth(request): -        redirect("/login") - -    username = request.COOKIES.get('user') - -    return template('default', page='downloads', links=core_methods.status_downloads(), user=username, status=core_methods.status_server()) - - -@route('/logs') -def logs(): - -    if not check_auth(request): -        redirect("/login") - -    username = request.COOKIES.get('user') - -    return template('default', page='logs', links=core_methods.status_downloads(), user=username, status=core_methods.status_server()) - -@route('/json/links') -def get_links(): -    response.header['Cache-Control'] = 'no-cache, must-revalidate' -    response.content_type = 'application/json' - -    if not check_auth(request): -        abort(404, "No Access") - -    json = '{ "downloads": [' - -    downloads = core_methods.status_downloads() -    ids = [] - -    for dl in downloads: -        ids.append(dl['id']) -        json += '{' -        json += '"id": %s, "name": "%s", "speed": %s, "eta": "%s", "kbleft": %s, "size": %s, "percent": %s, "wait": "%s", "status": "%s"'\ -            % (str(dl['id']), str(dl['name']), str(int(dl['speed'])), str(core.format_time(dl['eta'])), dl['kbleft'], dl['size'], dl['percent'], str(core.format_time(dl['wait_until'] - time.time())), dl['status']) - -        json += "}," - -    if json.endswith(","): json = json[:-1] - -    json += '], "ids": %s }' % str(ids) - -    return json - -@route('/json/status') -def get_status(): -    response.header['Cache-Control'] = 'no-cache, must-revalidate' -    response.content_type = 'application/json' - -    if not check_auth(request): -        abort(404, "No Access") - -    data = core_methods.status_server() - -    if data['pause']: -        status = "paused" -    else: -        status = "running" - -    json = '{ "status": "%s", "speed": "%s", "queue": "%s" }' % (status, str(int(data['speed'])), str(data['queue'])) - -    return json -@route('json/addpackage', method='POST') -def add_package(): -    response.header['Cache-Control'] = 'no-cache, must-revalidate' -    response.content_type = 'application/json' -     -    if not check_auth(request): -        abort(404, "No Access") -     -    links = request.POST['links'].split('\n') -    name = request.POST['name'] -    core_methods.add_package(name, links) - -@route('/json/addlinks', method='POST') -def add_links(): -    response.header['Cache-Control'] = 'no-cache, must-revalidate' -    response.content_type = 'application/json' - -    if not check_auth(request): -        abort(404, "No Access") - -    links = request.POST['links'].split('\n') - -    core.add_links(links) -     -    return "{}" - -@route('/json/pause') -def pause(): -    response.header['Cache-Control'] = 'no-cache, must-revalidate' -    response.content_type = 'application/json' - -    if not check_auth(request): -        abort(404, "No Access") - -    core.thread_list.pause = True - -    return "{}" - - -@route('/json/play') -def play(): -    response.header['Cache-Control'] = 'no-cache, must-revalidate' -    response.content_type = 'application/json' - -    if not check_auth(request): -        abort(404, "No Access") - -    core.thread_list.pause = False - -    return "{}" - -@route('/favicon.ico') -def favicon(): -     -    if request.HEADER("HTTP_IF_MODIFIED_SINCE") == TIME: abort(304, "Not Modified") - -    response.header['Last-Modified'] = TIME - -    send_file('favicon.ico', root=(PATH + 'static/')) - -@route('static/:section/:filename') -def static_folder(section, filename): -     -    if request.HEADER("HTTP_IF_MODIFIED_SINCE") == TIME: abort(304, "Not Modified") - -    response.header['Last-Modified'] = TIME -    send_file(filename, root=(PATH + 'static/' + section)) - -@route('/static/:filename') -def static_file(filename): - -    if request.HEADER("HTTP_IF_MODIFIED_SINCE") == TIME: abort(304, "Not Modified") -     -    response.header['Last-Modified'] = TIME -    send_file(filename, root=(PATH + 'static/')) - - -def check_auth(req): - -    try: -        user = req.COOKIES.get('user') -        id = int(req.COOKIES.get('id')) -        ua = req.HEADER("HTTP_USER_AGENT") -        ip = req.HEADER("REMOTE_ADDR") - -        if USERS[id]['user'] == user and USERS[id]['ua'] == ua and USERS[id]['ip'] == ip: -            return True -    except: -        return False - -    return False - - -class WebServer(threading.Thread): -    def __init__(self, pycore): -        threading.Thread.__init__(self) - -        global core, core_methods, TIME -        core = pycore -        core_methods = pycore.server_methods -        self.core = pycore -        self.setDaemon(True) -         -        if pycore.config['general']['debug_mode']: -            bottle.debug(True) -            TIME = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime()) -        else: -            bottle.debug(False) - -        #@TODO remove -        #TIME = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime()) - -        bottle.TEMPLATE_PATH.append('./module/web/templates/') -     -    def run(self): -        self.core.logger.info("Starting Webinterface on %s port %s" % (self.core.config['webinterface']['listenaddr'],self.core.config['webinterface']['port'])) -        try: -            run(host=self.core.config['webinterface']['listenaddr'], port=int(self.core.config['webinterface']['port']), quiet=True) -        except: -            self.core.logger.error("Failed starting webserver, no webinterface available: Can't create socket") -            exit()
\ No newline at end of file diff --git a/module/web/__init__.py b/module/web/ajax/__init__.py index e69de29bb..e69de29bb 100644 --- a/module/web/__init__.py +++ b/module/web/ajax/__init__.py diff --git a/module/web/ajax/models.py b/module/web/ajax/models.py new file mode 100644 index 000000000..71a836239 --- /dev/null +++ b/module/web/ajax/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/module/web/ajax/tests.py b/module/web/ajax/tests.py new file mode 100644 index 000000000..2247054b3 --- /dev/null +++ b/module/web/ajax/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): +    def test_basic_addition(self): +        """ +        Tests that 1 + 1 always equals 2. +        """ +        self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/module/web/ajax/urls.py b/module/web/ajax/urls.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/module/web/ajax/urls.py diff --git a/module/web/ajax/views.py b/module/web/ajax/views.py new file mode 100644 index 000000000..60f00ef0e --- /dev/null +++ b/module/web/ajax/views.py @@ -0,0 +1 @@ +# Create your views here. diff --git a/module/web/bottle.py b/module/web/bottle.py deleted file mode 100644 index 41a8c8fc0..000000000 --- a/module/web/bottle.py +++ /dev/null @@ -1,1231 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Bottle is a fast and simple micro-framework for small web applications. It -offers request dispatching (Routes) with url parameter support, templates, -key/value databases, a built-in HTTP Server and adapters for many third party -WSGI/HTTP-server and template engines - all in a single file and with no -dependencies other than the Python Standard Library. - -Homepage and documentation: http://wiki.github.com/defnull/bottle - -Special thanks to Stefan Matthias Aust [http://github.com/sma] -  for his contribution to SimpleTemplate - -Licence (MIT) -------------- - -    Copyright (c) 2009, Marcel Hellkamp. - -    Permission is hereby granted, free of charge, to any person obtaining a copy -    of this software and associated documentation files (the "Software"), to deal -    in the Software without restriction, including without limitation the rights -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -    copies of the Software, and to permit persons to whom the Software is -    furnished to do so, subject to the following conditions: - -    The above copyright notice and this permission notice shall be included in -    all copies or substantial portions of the Software. - -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -    THE SOFTWARE. - - -Example -------- - -    from bottle import route, run, request, response, send_file, abort - -    @route('/') -    def hello_world(): -        return 'Hello World!' - -    @route('/hello/:name') -    def hello_name(name): -        return 'Hello %s!' % name - -    @route('/hello', method='POST') -    def hello_post(): -        name = request.POST['name'] -        return 'Hello %s!' % name - -    @route('/static/:filename#.*#') -    def static_file(filename): -        send_file(filename, root='/path/to/static/files/') - -    run(host='localhost', port=8080) - -""" - -__author__ = 'Marcel Hellkamp' -__version__ = '0.6.4' -__license__ = 'MIT' - -import types -import sys -import cgi -import mimetypes -import os -import os.path -import traceback -import re -import random -import threading -import time -import warnings -import email.utils -from wsgiref.headers import Headers as HeaderWrapper -from Cookie import SimpleCookie -import anydbm as dbm -import subprocess -import thread - - -try: -    from urlparse import parse_qs -except ImportError: # pragma: no cover -    from cgi import parse_qs - -try: -    import cPickle as pickle -except ImportError: # pragma: no cover -    import pickle as pickle -   -try: -    try: -        from json import dumps as json_dumps -    except ImportError: # pragma: no cover -        from simplejson import dumps as json_dumps  -except ImportError: # pragma: no cover -    json_dumps = None - - - - - - -# Exceptions and Events - -class BottleException(Exception): -    """ A base class for exceptions used by bottle. """ -    pass - - -class HTTPError(BottleException): -    """ -    A way to break the execution and instantly jump to an error handler. -    """ -    def __init__(self, status, text): -        self.output = text -        self.http_status = int(status) -        BottleException.__init__(self, status, text) - -    def __repr__(self): -        return 'HTTPError(%d,%s)' % (self.http_status, repr(self.output)) - -    def __str__(self): -        return HTTP_ERROR_TEMPLATE % { -            'status' : self.http_status, -            'url' : request.path, -            'error_name' : HTTP_CODES.get(self.http_status, 'Unknown').title(), -            'error_message' : ''.join(self.output) -        } - - -class BreakTheBottle(BottleException): -    """ -    Not an exception, but a straight jump out of the controller code. -    Causes the Bottle to instantly call start_response() and return the -    content of output -    """ -    def __init__(self, output): -        self.output = output - - - - - - -# WSGI abstraction: Request and response management - -_default_app = None -def default_app(newapp = None): -    """ -    Returns the current default app or sets a new one. -    Defaults to an instance of Bottle -    """ -    global _default_app -    if newapp: -        _default_app = newapp -    if not _default_app: -        _default_app = Bottle() -    return _default_app - - -class Bottle(object): - -    def __init__(self, catchall=True, optimize=False, autojson=True): -        self.simple_routes = {} -        self.regexp_routes = {} -        self.default_route = None -        self.error_handler = {} -        self.optimize = optimize -        self.autojson = autojson -        self.catchall = catchall -        self.serve = True - -    def match_url(self, url, method='GET'): -        """ -        Returns the first matching handler and a parameter dict or (None, None) -        """ -        url = url.strip().lstrip("/ ") -        # Search for static routes first -        route = self.simple_routes.get(method,{}).get(url,None) -        if route: -            return (route, {}) -         -        routes = self.regexp_routes.get(method,[]) -        for i in range(len(routes)): -            match = routes[i][0].match(url) -            if match: -                handler = routes[i][1] -                if i > 0 and self.optimize and random.random() <= 0.001: -                    routes[i-1], routes[i] = routes[i], routes[i-1] -                return (handler, match.groupdict()) -        if self.default_route: -            return (self.default_route, {}) -        if method == 'HEAD': # Fall back to GET -            return self.match_url(url) -        else: -            return (None, None) - -    def add_controller(self, route, controller, **kargs): -        """ Adds a controller class or object """ -        if '{action}' not in route and 'action' not in kargs: -            raise BottleException("Routes to controller classes or object MUST" -                " contain an {action} placeholder or use the action-parameter") -        for action in (m for m in dir(controller) if not m.startswith('_')): -            handler = getattr(controller, action) -            if callable(handler) and action == kargs.get('action', action): -                self.add_route(route.replace('{action}', action), handler, **kargs) - -    def add_route(self, route, handler, method='GET', simple=False, **kargs): -        """ Adds a new route to the route mappings. """ -        if isinstance(handler, type) and issubclass(handler, BaseController): -            handler = handler() -        if isinstance(handler, BaseController): -            self.add_controller(route, handler, method=method, simple=simple, **kargs) -            return -        method = method.strip().upper() -        route = route.strip().lstrip('$^/ ').rstrip('$^ ') -        if re.match(r'^(\w+/)*\w*$', route) or simple: -            self.simple_routes.setdefault(method, {})[route] = handler -        else: -            route = re.sub(r':([a-zA-Z_]+)(?P<uniq>[^\w/])(?P<re>.+?)(?P=uniq)', -                           r'(?P<\1>\g<re>)',route) -            route = re.sub(r':([a-zA-Z_]+)', r'(?P<\1>[^/]+)', route) -            route = re.compile('^%s$' % route) -            self.regexp_routes.setdefault(method, []).append([route, handler]) - -    def route(self, url, **kargs): -        """ -        Decorator for request handler. -        Same as add_route(url, handler, **kargs). -        """ -        def wrapper(handler): -            self.add_route(url, handler, **kargs) -            return handler -        return wrapper - -    def set_default(self, handler): -        self.default_route = handler - -    def default(self): -        """ Decorator for request handler. Same as add_defroute( handler ).""" -        def wrapper(handler): -            self.set_default(handler) -            return handler -        return wrapper - -    def set_error_handler(self, code, handler): -        """ Adds a new error handler. """ -        self.error_handler[int(code)] = handler - -    def error(self, code=500): -        """ -        Decorator for error handler. -        Same as set_error_handler(code, handler). -        """ -        def wrapper(handler): -            self.set_error_handler(code, handler) -            return handler -        return wrapper - -    def cast(self, out): -        """ -        Cast the output to an iterable of strings or something WSGI can handle. -        Set Content-Type and Content-Length when possible. Then clear output -        on HEAD requests. -        Supports: False, str, unicode, list(unicode), dict(), open() -        """ -        if not out: -            out = [] -            response.header['Content-Length'] = '0' -        elif isinstance(out, types.StringType): -            out = [out] -        elif isinstance(out, unicode): -            out = [out.encode(response.charset)] -        elif isinstance(out, list) and isinstance(out[0], unicode): -            out = map(lambda x: x.encode(response.charset), out) -        elif self.autojson and json_dumps and isinstance(out, dict): -            out = [json_dumps(out)] -            response.content_type = 'application/json' -        elif hasattr(out, 'read'): -            out = request.environ.get('wsgi.file_wrapper', -                  lambda x: iter(lambda: x.read(8192), ''))(out) -        if isinstance(out, list) and len(out) == 1: -            response.header['Content-Length'] = str(len(out[0])) -        if not hasattr(out, '__iter__'): -            raise TypeError('Request handler for route "%s" returned [%s] ' -            'which is not iterable.' % (request.path, type(out).__name__)) -        return out - - -    def __call__(self, environ, start_response): -        """ The bottle WSGI-interface. """ -        request.bind(environ) -        response.bind() -        try: # Unhandled Exceptions -            try: # Bottle Error Handling -                if not self.serve: -                    abort(503, "Server stopped") -                handler, args = self.match_url(request.path, request.method) -                if not handler: -                    raise HTTPError(404, "Not found") -                output = handler(**args) -                db.close() -            except BreakTheBottle, e: -                output = e.output -            except HTTPError, e: -                response.status = e.http_status -                output = self.error_handler.get(response.status, str)(e) -            output = self.cast(output) -            if response.status in (100, 101, 204, 304) or request.method == 'HEAD': -                output = [] # rfc2616 section 4.3 -        except (KeyboardInterrupt, SystemExit, MemoryError): -            raise -        except Exception, e: -            response.status = 500 -            if self.catchall: -                err = "Unhandled Exception: %s\n" % (repr(e)) -                if DEBUG: -                    err += TRACEBACK_TEMPLATE % traceback.format_exc(10) -                output = [str(HTTPError(500, err))] -                request._environ['wsgi.errors'].write(err) -            else: -                raise -        status = '%d %s' % (response.status, HTTP_CODES[response.status]) -        start_response(status, response.wsgiheaders()) -        return output - - - -class Request(threading.local): -    """ Represents a single request using thread-local namespace. """ - -    def bind(self, environ): -        """ -        Binds the enviroment of the current request to this request handler -        """ -        self._environ = environ -        self.environ = self._environ -        self._GET = None -        self._POST = None -        self._GETPOST = None -        self._COOKIES = None -        self.path = self._environ.get('PATH_INFO', '/').strip() -        if not self.path.startswith('/'): -            self.path = '/' + self.path - -    @property -    def method(self): -        """ Get the request method (GET,POST,PUT,DELETE,...) """ -        return self._environ.get('REQUEST_METHOD', 'GET').upper() - -    @property -    def query_string(self): -        """ Get content of QUERY_STRING """ -        return self._environ.get('QUERY_STRING', '') - -    @property -    def input_length(self): -        """ Get content of CONTENT_LENGTH """ -        try: -            return max(0,int(self._environ.get('CONTENT_LENGTH', '0'))) -        except ValueError: -            return 0 - -    @property -    def GET(self): -        """ Get a dict with GET parameters. """ -        if self._GET is None: -            data = parse_qs(self.query_string, keep_blank_values=True) -            self._GET = {} -            for key, value in data.iteritems(): -                if len(value) == 1: -                    self._GET[key] = value[0] -                else: -                    self._GET[key] = value -        return self._GET - -    @property -    def POST(self): -        """ Get a dict with parsed POST or PUT data. """ -        if self._POST is None: -            data = cgi.FieldStorage(fp=self._environ['wsgi.input'], -                environ=self._environ, keep_blank_values=True) -            self._POST  = {} -            for item in data.list: -                name = item.name -                if not item.filename: -                    item = item.value -                self._POST.setdefault(name, []).append(item) -            for key in self._POST: -                if len(self._POST[key]) == 1: -                    self._POST[key] = self._POST[key][0] -        return self._POST - -    @property -    def params(self): -        """ Returns a mix of GET and POST data. POST overwrites GET """ -        if self._GETPOST is None: -            self._GETPOST = dict(self.GET) -            self._GETPOST.update(dict(self.POST)) -        return self._GETPOST - -    @property -    def COOKIES(self): -        """ Returns a dict with COOKIES. """ -        if self._COOKIES is None: -            raw_dict = SimpleCookie(self._environ.get('HTTP_COOKIE','')) -            self._COOKIES = {} -            for cookie in raw_dict.itervalues(): -                self._COOKIES[cookie.key] = cookie.value -        return self._COOKIES - -    def HEADER(self, header): -        """Returns HTTP header""" -        return self._environ.get(header, '') - -class Response(threading.local): -    """ Represents a single response using thread-local namespace. """ - -    def bind(self): -        """ Clears old data and creates a brand new Response object """ -        self._COOKIES = None -        self.status = 200 -        self.header_list = [] -        self.header = HeaderWrapper(self.header_list) -        self.content_type = 'text/html' -        self.error = None -        self.charset = 'utf8' - -    def wsgiheaders(self): -        ''' Returns a wsgi conform list of header/value pairs ''' -        for c in self.COOKIES.itervalues(): -            self.header.add_header('Set-Cookie', c.OutputString()) -        return [(h.title(), str(v)) for h, v in self.header.items()] - -    @property -    def COOKIES(self): -        if not self._COOKIES: -            self._COOKIES = SimpleCookie() -        return self._COOKIES - -    def set_cookie(self, key, value, **kargs): -        """ -        Sets a Cookie. Optional settings: -        expires, path, comment, domain, max-age, secure, version, httponly -        """ -        self.COOKIES[key] = value -        for k, v in kargs.iteritems(): -            self.COOKIES[key][k] = v - -    def get_content_type(self): -        """ Get the current 'Content-Type' header. """ -        return self.header['Content-Type'] -         -    def set_content_type(self, value): -        if 'charset=' in value: -            self.charset = value.split('charset=')[-1].split(';')[0].strip() -        self.header['Content-Type'] = value - -    content_type = property(get_content_type, set_content_type, None, -                            get_content_type.__doc__) - - -class BaseController(object): -    _singleton = None -    def __new__(cls, *a, **k): -        if not cls._singleton: -            cls._singleton = object.__new__(cls, *a, **k) -        return cls._singleton - - -def abort(code=500, text='Unknown Error: Appliction stopped.'): -    """ Aborts execution and causes a HTTP error. """ -    raise HTTPError(code, text) - - -def redirect(url, code=307): -    """ Aborts execution and causes a 307 redirect """ -    response.status = code -    response.header['Location'] = url -    raise BreakTheBottle("") - - -def send_file(filename, root, guessmime = True, mimetype = None): -    """ Aborts execution and sends a static files as response. """ -    root = os.path.abspath(root) + os.sep -    filename = os.path.abspath(os.path.join(root, filename.strip('/\\'))) - -    if not filename.startswith(root): -        abort(401, "Access denied.") -    if not os.path.exists(filename) or not os.path.isfile(filename): -        abort(404, "File does not exist.") -    if not os.access(filename, os.R_OK): -        abort(401, "You do not have permission to access this file.") - -    if guessmime and not mimetype: -        mimetype = mimetypes.guess_type(filename)[0] -    if not mimetype: mimetype = 'text/plain' -    response.content_type = mimetype - -    stats = os.stat(filename) -    if 'Last-Modified' not in response.header: -        lm = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(stats.st_mtime)) -        response.header['Last-Modified'] = lm -    if 'HTTP_IF_MODIFIED_SINCE' in request.environ: -        ims = request.environ['HTTP_IF_MODIFIED_SINCE'] -        # IE sends "<date>; length=146" -        ims = ims.split(";")[0].strip() -        ims = parse_date(ims) -        if ims is not None and ims >= stats.st_mtime: -           abort(304, "Not modified") -    if 'Content-Length' not in response.header: -        response.header['Content-Length'] = str(stats.st_size) -    raise BreakTheBottle(open(filename, 'rb')) - - -def parse_date(ims): -    """ -    Parses date strings usually found in HTTP header and returns UTC epoch. -    Understands rfc1123, rfc850 and asctime. -    """ -    try: -        ts = email.utils.parsedate_tz(ims) -        if ts is not None: -            if ts[9] is None: -                return time.mktime(ts[:8] + (0,)) - time.timezone -            else: -                return time.mktime(ts[:8] + (0,)) - ts[9] - time.timezone -    except (ValueError, IndexError): -        return None - - - - - - -# Decorators - -def validate(**vkargs): -    """ -    Validates and manipulates keyword arguments by user defined callables.  -    Handles ValueError and missing arguments by raising HTTPError(403). -    """ -    def decorator(func): -        def wrapper(**kargs): -            for key, value in vkargs.iteritems(): -                if key not in kargs: -                    abort(403, 'Missing parameter: %s' % key) -                try: -                    kargs[key] = value(kargs[key]) -                except ValueError, e: -                    abort(403, 'Wrong parameter format for: %s' % key) -            return func(**kargs) -        return wrapper -    return decorator - - -def route(url, **kargs): -    """ -    Decorator for request handler. Same as add_route(url, handler, **kargs). -    """ -    return default_app().route(url, **kargs) - -def default(): -    """ -    Decorator for request handler. Same as set_default(handler). -    """ -    return default_app().default() - -def error(code=500): -    """ -    Decorator for error handler. Same as set_error_handler(code, handler). -    """ -    return default_app().error(code) - - - - - - -# Server adapter - -class WSGIAdapter(object): -    def run(self, handler): # pragma: no cover -        pass - -    def __repr__(self): -        return "%s()" % (self.__class__.__name__) - - -class CGIServer(WSGIAdapter): -    def run(self, handler): -        from wsgiref.handlers import CGIHandler -        CGIHandler().run(handler) - - -class ServerAdapter(WSGIAdapter): -    def __init__(self, host='127.0.0.1', port=8080, **kargs): -        WSGIAdapter.__init__(self) -        self.host = host -        self.port = int(port) -        self.options = kargs - -    def __repr__(self): -        return "%s (%s:%d)" % (self.__class__.__name__, self.host, self.port) - - -class WSGIRefServer(ServerAdapter): -    def run(self, handler): -        from wsgiref.simple_server import make_server -        srv = make_server(self.host, self.port, handler) -        srv.serve_forever() - - -class CherryPyServer(ServerAdapter): -    def run(self, handler): -        from cherrypy import wsgiserver -        server = wsgiserver.CherryPyWSGIServer((self.host, self.port), handler) -        server.start() - - -class FlupServer(ServerAdapter): -    def run(self, handler): -       from flup.server.fcgi import WSGIServer -       WSGIServer(handler, bindAddress=(self.host, self.port)).run() - - -class PasteServer(ServerAdapter): -    def run(self, handler): -        from paste import httpserver -        from paste.translogger import TransLogger -        app = TransLogger(handler) -        httpserver.serve(app, host=self.host, port=str(self.port)) - - -class FapwsServer(ServerAdapter): -    """ -    Extremly fast webserver using libev. -    See http://william-os4y.livejournal.com/ -    Experimental ... -    """ -    def run(self, handler): -        import fapws._evwsgi as evwsgi -        from fapws import base -        evwsgi.start(self.host, self.port) -        evwsgi.set_base_module(base) -        def app(environ, start_response): -            environ['wsgi.multiprocess'] = False -            return handler(environ, start_response) -        evwsgi.wsgi_cb(('',app)) -        evwsgi.run() - - -def run(app=None, server=WSGIRefServer, host='127.0.0.1', port=8080, -        interval=1, reloader=False, **kargs): -    """ Runs bottle as a web server. """ -    if not app: -        app = default_app() -     -    quiet = bool(kargs.get('quiet', False)) - -    # Instantiate server, if it is a class instead of an instance -    if isinstance(server, type): -        if issubclass(server, CGIServer): -            server = server() -        elif issubclass(server, ServerAdapter): -            server = server(host=host, port=port, **kargs) - -    if not isinstance(server, WSGIAdapter): -        raise RuntimeError("Server must be a subclass of WSGIAdapter") -  -    if not quiet and isinstance(server, ServerAdapter): # pragma: no cover -        if not reloader or os.environ.get('BOTTLE_CHILD') == 'true': -            print "Bottle server starting up (using %s)..." % repr(server) -            print "Listening on http://%s:%d/" % (server.host, server.port) -            print "Use Ctrl-C to quit." -            print -        else: -            print "Bottle auto reloader starting up..." - -    try: -        if reloader and interval: -            reloader_run(server, app, interval) -        else: -            server.run(app) -    except KeyboardInterrupt: -        if not quiet: # pragma: no cover -            print "Shutting Down..." - - -#TODO: If the parent process is killed (with SIGTERM) the childs survive... -def reloader_run(server, app, interval): -    if os.environ.get('BOTTLE_CHILD') == 'true': -        # We are a child process -        files = dict() -        for module in sys.modules.values(): -            file_path = getattr(module, '__file__', None) -            if file_path and os.path.isfile(file_path): -                file_split = os.path.splitext(file_path) -                if file_split[1] in ('.py', '.pyc', '.pyo'): -                    file_path = file_split[0] + '.py' -                    files[file_path] = os.stat(file_path).st_mtime -        thread.start_new_thread(server.run, (app,)) -        while True: -            time.sleep(interval) -            for file_path, file_mtime in files.iteritems(): -                if not os.path.exists(file_path): -                    print "File changed: %s (deleted)" % file_path -                elif os.stat(file_path).st_mtime > file_mtime: -                    print "File changed: %s (modified)" % file_path -                else: continue -                print "Restarting..." -                app.serve = False -                time.sleep(interval) # be nice and wait for running requests -                sys.exit(3) -    while True: -        args = [sys.executable] + sys.argv -        environ = os.environ.copy() -        environ['BOTTLE_CHILD'] = 'true' -        exit_status = subprocess.call(args, env=environ) -        if exit_status != 3: -            sys.exit(exit_status) - - - - - -# Templates - -class TemplateError(HTTPError): -    def __init__(self, message): -        HTTPError.__init__(self, 500, message) - -class BaseTemplate(object): -    def __init__(self, template='', name=None, filename=None, lookup=[]): -        """ -        Create a new template. -        If a name is provided, but no filename and no template string, the -        filename is guessed using the lookup path list. -        Subclasses can assume that either self.template or self.filename is set. -        If both are present, self.template should be used. -        """ -        self.name = name -        self.filename = filename -        self.template = template -        self.lookup = lookup -        if self.name and not self.filename: -            for path in self.lookup: -                fpath = os.path.join(path, self.name+'.tpl') -                if os.path.isfile(fpath): -                    self.filename = fpath -        if not self.template and not self.filename: -            raise TemplateError('Template (%s) not found.' % self.name) -        self.prepare() - -    def prepare(self): -        """ -        Run preparatios (parsing, caching, ...). -        It should be possible to call this multible times to refresh a template. -        """ -        raise NotImplementedError - -    def render(self, **args): -        """ -        Render the template with the specified local variables and return an -        iterator of strings (bytes). This must be thread save! -        """ -        raise NotImplementedError - - -class MakoTemplate(BaseTemplate): -    output_encoding=None -    input_encoding=None -    default_filters=None -    global_variables={} - -    def prepare(self): -        from mako.template import Template -        from mako.lookup import TemplateLookup -        #TODO: This is a hack... http://github.com/defnull/bottle/issues#issue/8 -        mylookup = TemplateLookup(directories=map(os.path.abspath, self.lookup)+['./']) -        if self.template: -            self.tpl = Template(self.template, -                                lookup=mylookup, -                                output_encoding=MakoTemplate.output_encoding, -                                input_encoding=MakoTemplate.input_encoding, -                                default_filters=MakoTemplate.default_filters -                                ) -        else: -            self.tpl = Template(filename=self.filename, -                                lookup=mylookup, -                                output_encoding=MakoTemplate.output_encoding, -                                input_encoding=MakoTemplate.input_encoding, -                                default_filters=MakoTemplate.default_filters -                                ) -  -    def render(self, **args): -        _defaults = MakoTemplate.global_variables.copy() -        _defaults.update(args) -        return self.tpl.render(**_defaults) - - -class CheetahTemplate(BaseTemplate): -    def prepare(self): -        from Cheetah.Template import Template -        self.context = threading.local() -        self.context.vars = {} -        if self.template: -            self.tpl = Template(source=self.template, searchList=[self.context.vars]) -        else: -            self.tpl = Template(file=self.filename, searchList=[self.context.vars]) -  -    def render(self, **args): -        self.context.vars.update(args) -        out = str(self.tpl) -        self.context.vars.clear() -        return [out] - - -class Jinja2Template(BaseTemplate): -    env = None # hopefully, a Jinja environment is actually thread-safe - -    def prepare(self): -        if not self.env: -            from jinja2 import Environment, FunctionLoader -            self.env = Environment(line_statement_prefix="#", loader=FunctionLoader(self.loader)) -        if self.template: -            self.tpl = self.env.from_string(self.template) -        else: -            self.tpl = self.env.get_template(self.filename) - -    def render(self, **args): -        return self.tpl.render(**args).encode("utf-8") -         -    def loader(self, name): -        if not name.endswith(".tpl"): -            for path in self.lookup: -                fpath = os.path.join(path, name+'.tpl') -                if os.path.isfile(fpath): -                    name = fpath -                    break -        f = open(name) -        try: return f.read() -        finally: f.close() - - -class SimpleTemplate(BaseTemplate): -    re_python = re.compile(r'^\s*%\s*(?:(if|elif|else|try|except|finally|for|' -                            'while|with|def|class)|(include|rebase)|(end)|(.*))') -    re_inline = re.compile(r'\{\{(.*?)\}\}') -    dedent_keywords = ('elif', 'else', 'except', 'finally') - -    def prepare(self): -        if self.template: -            code = self.translate(self.template) -            self.co = compile(code, '<string>', 'exec') -        else: -            code = self.translate(open(self.filename).read()) -            self.co = compile(code, self.filename, 'exec') - -    def translate(self, template): -        indent = 0 -        strbuffer = [] -        code = [] -        self.includes = dict() -        class PyStmt(str): -            def __repr__(self): return 'str(' + self + ')' -        def flush(allow_nobreak=False): -            if len(strbuffer): -                if allow_nobreak and strbuffer[-1].endswith("\\\\\n"): -                    strbuffer[-1]=strbuffer[-1][:-3] -                code.append(' ' * indent + "_stdout.append(%s)" % repr(''.join(strbuffer))) -                code.append((' ' * indent + '\n') * len(strbuffer)) # to preserve line numbers  -                del strbuffer[:] -        for line in template.splitlines(True): -            m = self.re_python.match(line) -            if m: -                flush(allow_nobreak=True) -                keyword, subtpl, end, statement = m.groups() -                if keyword: -                    if keyword in self.dedent_keywords: -                        indent -= 1 -                    code.append(" " * indent + line[m.start(1):]) -                    indent += 1 -                elif subtpl: -                    tmp = line[m.end(2):].strip().split(None, 1) -                    if not tmp: -                      code.append(' ' * indent + "_stdout.extend(_base)\n") -                    else: -                      name = tmp[0] -                      args = tmp[1:] and tmp[1] or '' -                      if name not in self.includes: -                        self.includes[name] = SimpleTemplate(name=name, lookup=self.lookup) -                      if subtpl == 'include': -                        code.append(' ' * indent +  -                                    "_ = _includes[%s].execute(_stdout, %s)\n" -                                    % (repr(name), args)) -                      else: -                        code.append(' ' * indent +  -                                    "_tpl['_rebase'] = (_includes[%s], dict(%s))\n" -                                    % (repr(name), args)) -                elif end: -                    indent -= 1 -                    code.append(' ' * indent + '#' + line[m.start(3):]) -                elif statement: -                    code.append(' ' * indent + line[m.start(4):]) -            else: -                splits = self.re_inline.split(line) # text, (expr, text)* -                if len(splits) == 1: -                    strbuffer.append(line) -                else: -                    flush() -                    for i in range(1, len(splits), 2): -                        splits[i] = PyStmt(splits[i]) -                    splits = [x for x in splits if bool(x)] -                    code.append(' ' * indent + "_stdout.extend(%s)\n" % repr(splits)) -        flush() -        return ''.join(code) - -    def execute(self, stdout, **args): -        args['_stdout'] = stdout -        args['_includes'] = self.includes -        args['_tpl'] = args -        eval(self.co, args) -        if '_rebase' in args: -            subtpl, args = args['_rebase'] -            args['_base'] = stdout[:] #copy stdout -            del stdout[:] # clear stdout -            return subtpl.execute(stdout, **args) -        return args -    def render(self, **args): -        """ Render the template using keyword arguments as local variables. """ -        stdout = [] -        self.execute(stdout, **args) -        return stdout -             - - -def template(tpl, template_adapter=SimpleTemplate, **args): -    ''' -    Get a rendered template as a string iterator. -    You can use a name, a filename or a template string as first parameter. -    ''' -    lookup = args.get('template_lookup', TEMPLATE_PATH) -    if tpl not in TEMPLATES or DEBUG: -        if "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl: -            TEMPLATES[tpl] = template_adapter(template=tpl, lookup=lookup) -        elif '.' in tpl: -            TEMPLATES[tpl] = template_adapter(filename=tpl, lookup=lookup) -        else: -            TEMPLATES[tpl] = template_adapter(name=tpl, lookup=lookup) -    if not TEMPLATES[tpl]: -        abort(500, 'Template (%s) not found' % tpl) -    args['abort'] = abort -    args['request'] = request -    args['response'] = response -    return TEMPLATES[tpl].render(**args) - - -def mako_template(tpl_name, **kargs): -    kargs['template_adapter'] = MakoTemplate -    return template(tpl_name, **kargs) - -def cheetah_template(tpl_name, **kargs): -    kargs['template_adapter'] = CheetahTemplate -    return template(tpl_name, **kargs) - -def jinja2_template(tpl_name, **kargs): -    kargs['template_adapter'] = Jinja2Template -    return template(tpl_name, **kargs) - -def view(tpl_name, **defaults): -    ''' Decorator: Rendes a template for a handler. -        Return a dict of template vars to fill out the template. -    ''' -    def decorator(func): -        def wrapper(**kargs): -            out = func(**kargs) -            defaults.update(out) -            return template(tpl_name, **defaults) -        return wrapper -    return decorator - -def mako_view(tpl_name, **kargs): -    kargs['template_adapter'] = MakoTemplate -    return view(tpl_name, **kargs) - -def cheetah_view(tpl_name, **kargs): -    kargs['template_adapter'] = CheetahTemplate -    return view(tpl_name, **kargs) - -def jinja2_view(tpl_name, **kargs): -    kargs['template_adapter'] = Jinja2Template -    return view(tpl_name, **kargs) - - - - - - - -# Database - -class BottleBucket(object): # pragma: no cover -    """ Memory-caching wrapper around anydbm """ -    def __init__(self, name): -        self.__dict__['name'] = name -        self.__dict__['db'] = dbm.open(DB_PATH + '/%s.db' % name, 'c') -        self.__dict__['mmap'] = {} -             -    def __getitem__(self, key): -        if key not in self.mmap: -            self.mmap[key] = pickle.loads(self.db[key]) -        return self.mmap[key] -     -    def __setitem__(self, key, value): -        if not isinstance(key, str): raise TypeError("Bottle keys must be strings") -        self.mmap[key] = value -     -    def __delitem__(self, key): -        if key in self.mmap: -            del self.mmap[key] -        del self.db[key] - -    def __getattr__(self, key): -        try: return self[key] -        except KeyError: raise AttributeError(key) - -    def __setattr__(self, key, value): -        self[key] = value - -    def __delattr__(self, key): -        try: del self[key] -        except KeyError: raise AttributeError(key) - -    def __iter__(self): -        return iter(self.ukeys()) -     -    def __contains__(self, key): -        return key in self.ukeys() -   -    def __len__(self): -        return len(self.ukeys()) - -    def keys(self): -        return list(self.ukeys()) - -    def ukeys(self): -      return set(self.db.keys()) | set(self.mmap.keys()) - -    def save(self): -        self.close() -        self.__init__(self.name) -     -    def close(self): -        for key in self.mmap: -            pvalue = pickle.dumps(self.mmap[key], pickle.HIGHEST_PROTOCOL) -            if key not in self.db or pvalue != self.db[key]: -                self.db[key] = pvalue -        self.mmap.clear() -        if hasattr(self.db, 'sync'): -            self.db.sync() -        if hasattr(self.db, 'close'): -            self.db.close() -         -    def clear(self): -        for key in self.db: -            del self.db[key] -        self.mmap.clear() -         -    def update(self, other): -        self.mmap.update(other) - -    def get(self, key, default=None): -        try: -            return self[key] -        except KeyError: -            if default: -                return default -            raise - - -class BottleDB(threading.local): # pragma: no cover -    """ Holds multible BottleBucket instances in a thread-local way. """ -    def __init__(self): -        self.__dict__['open'] = {} -         -    def __getitem__(self, key): -        warnings.warn("Please do not use bottle.db anymore. This feature is deprecated. You may use anydb directly.", DeprecationWarning) -        if key not in self.open and not key.startswith('_'): -            self.open[key] = BottleBucket(key) -        return self.open[key] - -    def __setitem__(self, key, value): -        if isinstance(value, BottleBucket): -            self.open[key] = value -        elif hasattr(value, 'items'): -            if key not in self.open: -                self.open[key] = BottleBucket(key) -            self.open[key].clear() -            for k, v in value.iteritems(): -                self.open[key][k] = v -        else: -            raise ValueError("Only dicts and BottleBuckets are allowed.") - -    def __delitem__(self, key): -        if key not in self.open: -            self.open[key].clear() -            self.open[key].save() -            del self.open[key] - -    def __getattr__(self, key): -        try: return self[key] -        except KeyError: raise AttributeError(key) - -    def __setattr__(self, key, value): -        self[key] = value - -    def __delattr__(self, key): -        try: del self[key] -        except KeyError: raise AttributeError(key) - -    def save(self): -        self.close() -        self.__init__() -     -    def close(self): -        for db in self.open: -            self.open[db].close() -        self.open.clear() - - - - - - -# Modul initialization and configuration - -DB_PATH = './' -TEMPLATE_PATH = ['./', './views/'] -TEMPLATES = {} -DEBUG = False -HTTP_CODES = { -    100: 'CONTINUE', -    101: 'SWITCHING PROTOCOLS', -    200: 'OK', -    201: 'CREATED', -    202: 'ACCEPTED', -    203: 'NON-AUTHORITATIVE INFORMATION', -    204: 'NO CONTENT', -    205: 'RESET CONTENT', -    206: 'PARTIAL CONTENT', -    300: 'MULTIPLE CHOICES', -    301: 'MOVED PERMANENTLY', -    302: 'FOUND', -    303: 'SEE OTHER', -    304: 'NOT MODIFIED', -    305: 'USE PROXY', -    306: 'RESERVED', -    307: 'TEMPORARY REDIRECT', -    400: 'BAD REQUEST', -    401: 'UNAUTHORIZED', -    402: 'PAYMENT REQUIRED', -    403: 'FORBIDDEN', -    404: 'NOT FOUND', -    405: 'METHOD NOT ALLOWED', -    406: 'NOT ACCEPTABLE', -    407: 'PROXY AUTHENTICATION REQUIRED', -    408: 'REQUEST TIMEOUT', -    409: 'CONFLICT', -    410: 'GONE', -    411: 'LENGTH REQUIRED', -    412: 'PRECONDITION FAILED', -    413: 'REQUEST ENTITY TOO LARGE', -    414: 'REQUEST-URI TOO LONG', -    415: 'UNSUPPORTED MEDIA TYPE', -    416: 'REQUESTED RANGE NOT SATISFIABLE', -    417: 'EXPECTATION FAILED', -    500: 'INTERNAL SERVER ERROR', -    501: 'NOT IMPLEMENTED', -    502: 'BAD GATEWAY', -    503: 'SERVICE UNAVAILABLE', -    504: 'GATEWAY TIMEOUT', -    505: 'HTTP VERSION NOT SUPPORTED', -} - -HTTP_ERROR_TEMPLATE = """ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> -<html> -    <head> -        <title>Error %(status)d: %(error_name)s</title> -    </head> -    <body> -        <h1>Error %(status)d: %(error_name)s</h1> -        <p>Sorry, the requested URL <tt>%(url)s</tt> caused an error:</p> -        <pre> -            %(error_message)s -        </pre> -    </body> -</html> -""" - -TRACEBACK_TEMPLATE = """ -<h2>Traceback:</h2> -<pre> -%s -</pre> -""" - -request = Request() -response = Response() -db = BottleDB() -local = threading.local() - -#TODO: Global and app local configuration (debug, defaults, ...) is a mess - -def debug(mode=True): -    global DEBUG -    DEBUG = bool(mode) - -def optimize(mode=True): -    default_app().optimize = bool(mode) - - diff --git a/module/web/main.html b/module/web/main.html deleted file mode 100644 index 87f0d7408..000000000 --- a/module/web/main.html +++ /dev/null @@ -1,29 +0,0 @@ -<title>pyLoad - Webinterface</title> -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de"> -    <head>  -        <title>pyLoad - Webinterface</title> -        <script src="main.js" type="text/javascript"></script> -    </head> -    <body> -        <h1>pyLoad - Webinterface</h1> -        <div name="status_server"> -            Status: running  Speed: 600kb/s  Files in queue: 0  -        </div> -        <div name="actions"> -            <div id="add_urls"> -                <form name="add_urls_form"> -                    <input type="text" name="new_url" /> -                    <input type="button" value="Add Link" onclick="addUrl(document.add_urls_form.new_url.value)" > -                </form> -            </div> -            (START) (PAUSE) (ADD) -        </div> -        <h2>Downloads</h2> -        <div id="downloads"> -            Lade Downloads -        </div> -    </body> -</html> - diff --git a/module/web/main.js b/module/web/main.js deleted file mode 100644 index a286df991..000000000 --- a/module/web/main.js +++ /dev/null @@ -1,42 +0,0 @@ -function getXmlHttpRequestObject() { -    if (window.XMLHttpRequest) { -        return new XMLHttpRequest(); //Not IE -    } else if(window.ActiveXObject) { -        return new ActiveXObject("Microsoft.XMLHTTP"); //IE -    } else { -        alert("Your browser doesn't support the XmlHttpRequest object.  Better upgrade to Firefox."); -    } -} -var req = getXmlHttpRequestObject(); - -function getDownloads() { -    req.onreadystatechange = function() { -        if (req.readyState == 4) { -            if(req.status==200) { -                document.getElementById('downloads').innerHTML = req.responseText; -            } else { -                alert("Fehler:\nHTTP-Status: "+req.status+"\nHTTP-Statustext: "+req.statusText); -            } -        }; -    } -    req.open("GET", '/downloads', true); -    req.send(null); -} - -function addUrl(new_url) { -    req.onreadystatechange = function() { -        if (req.readyState == 4) { -            if(req.status==200) { -                document.getElementById('add_urls').innerHTML = req.responseText; -            } else { -                alert("Fehler:\nHTTP-Status: "+req.status+"\nHTTP-Statustext: "+req.statusText); -            } -        }; -    } -    url = "/add=" + new_url -    req.open("GET", url, true); -    req.send(null); -} - -window.setInterval("getDownloads()", 1000); - diff --git a/module/web/manage.py b/module/web/manage.py new file mode 100644 index 000000000..ae9495854 --- /dev/null +++ b/module/web/manage.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +from django.core.management import execute_manager + +try: +    import settings # Assumed to be in the same directory. +except ImportError: +    import sys +    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) +    sys.exit(1) + +if __name__ == "__main__": +    execute_manager(settings) diff --git a/module/web/media/css/default.css b/module/web/media/css/default.css new file mode 100644 index 000000000..b5701cf43 --- /dev/null +++ b/module/web/media/css/default.css @@ -0,0 +1,145 @@ +div.no{display:inline;margin:0;padding:0;}.hidden{display:none;} +div.error{background:#fcc url(media/img/error.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #faa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;} +div.info{background:#ccf url(static/default/info.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #aaf;font-size:90%;margin:0;padding-left:3em;overflow:hidden;} +div.success{background:#cfc url(static/default/success.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #afa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;} +div.notify{background:#ffc url(media/img/notify.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #ffa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;} +.medialeft{float:left;}.mediaright{float:right;} +.mediacenter{display:block;margin-left:auto;margin-right:auto;} +.leftalign{text-align:left;} +.centeralign{text-align:center;} +.rightalign{text-align:right;} +em.u{font-style:normal;text-decoration:underline;} +em em.u{font-style:italic;} +.code .br0{color:#6c6;} +.code .co1{color:#808080;font-style:italic;} +.code .co2{color:#808080;font-style:italic;} +.code .co3{color:#808080;} +.code .coMULTI{color:#808080;font-style:italic;} +.code .es0{color:#009;font-weight:bold;}.code .kw1{color:#b1b100;} +.code .kw2{color:#000;font-weight:bold;}.code .kw3{color:#006;} +.code .kw4{color:#933;}.code .kw5{color:#00f;}.code .me1{color:#060;}.code .me2{color:#060;} +.code .nu0{color:#c6c;}.code .re0{color:#00f;}.code .re1{color:#00f;}.code .re2{color:#00f;}.code .re3{color:#f33;font-weight:bold;}.code .re4{color:#099;}.code .st0{color:#f00;}.code .sy0{color:#6c6;} +div.dokuwiki table.pagelist,div.dokuwiki table.ul{border:0;padding:0;border-spacing:0;margin-bottom:1em;border-collapse:collapse;} +div.dokuwiki table.pagelist tr{border-top:1px solid #8cacbb;border-bottom:1px solid #8cacbb;} +div.dokuwiki table.pagelist th,div.dokuwiki table.pagelist td{padding:1px 1em 1px 0;} +div.dokuwiki table.ul th,div.dokuwiki table.ul td{padding:0 1em 0 0;} +div.dokuwiki table.ul ul{margin:0 0 0 1.5em;} +div.dokuwiki table.pagelist th,div.dokuwiki table.ul th{background-color:#dee7ec;} +div.dokuwiki th.page,div.dokuwiki th.date,div.dokuwiki th.user,div.dokuwiki th.desc,div.dokuwiki th.comments,div.dokuwiki th.linkbacks,div.dokuwiki th.tags,div.dokuwiki td.date,div.dokuwiki td.user,div.dokuwiki td.desc,div.dokuwiki td.comments,div.dokuwiki td.linkbacks,div.dokuwiki td.tags{color:#666;font-size:80%;} +div.dokuwiki td.date{text-align:right;}div.dokuwiki div.include div.secedit{float:right;margin-left:1em;margin-top:-18px;} +div.dokuwiki div.inclmeta{border-top:1px dotted #8cacbb;padding-top:0.2em;color:#666;font-size:80%;line-height:1.25;margin-top:0.5em;margin-bottom:2em;} +div.dokuwiki div.inclmeta a.permalink{background:transparent url(media/img/link.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;} +div.dokuwiki div.inclmeta abbr.published{background:transparent url(media/img/date.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;border-bottom:0;} +div.dokuwiki div.inclmeta span.author{background:transparent url(media/img/user.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;} +div.dokuwiki div.inclmeta span.comment{background:transparent url(media/img/comment.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;} +div.dokuwiki div.inclmeta div.tags{border-top:0;font-size:100%;float:right;clear:none;}#plugin__manager{}#plugin__manager h2{margin-left:0;} +#plugin__manager form{display:block;margin:0;padding:0;} +#plugin__manager legend{display:none;} +#plugin__manager fieldset{width:auto;} +#plugin__manager .button{margin:0;} +#plugin__manager p,#plugin__manager label{text-align:left;} +#plugin__manager .hidden{display:none;}#plugin__manager .new{background:#dee7ec;} +#plugin__manager input[disabled]{color:#ccc;border-color:#ccc;} +#plugin__manager .pm_menu,#plugin__manager .pm_info{margin-left:0;text-align:left;} +#plugin__manager .pm_menu{float:left;width:48%;} +#plugin__manager .pm_info{float:right;width:50%;} +#plugin__manager .common{}#plugin__manager .common form{} +#plugin__manager .common fieldset{margin:0;padding:0 0 1.0em 0;text-align:left;border:none;} +#plugin__manager .common label{padding:0 0 0.5em 0;} +#plugin__manager .common input{} +#plugin__manager .common input.edit{width:24em;margin:0.5em;} +#plugin__manager .common .button{} +#plugin__manager form.plugins{} +#plugin__manager .plugins fieldset{color:#000;background:#fff;text-align:right;border-top:none;border-right:none;border-left:none;} +#plugin__manager .plugins fieldset.protected{background:#fdd;color:#000;} +#plugin__manager .plugins fieldset.disabled{background:#e0e0e0;color:#a8a8a8;} +#plugin__manager .plugins .legend{color:#000;background:inherit;display:block;margin:0;padding:0;font-size:1em;line-height:1.4em;font-weight:normal;text-align:left;float:left;padding:0;clear:none;} +#plugin__manager .plugins .button{font-size:95%;}#plugin__manager .plugins fieldset.buttons{border:none;} +#plugin__manager .plugins fieldset.buttons .button{float:left;} +#plugin__manager .pm_info h3{margin-left:0;}#plugin__manager .pm_info dl{margin:1em 0;padding:0;} +#plugin__manager .pm_info dt{width:6em;float:left;clear:left;margin:0;padding:0;} +#plugin__manager .pm_info dd{margin:0 0 0 7em;padding:0;background:none;} +#plugin__manager .plugins .enable{float:left;width:auto;margin-right:0.5em;} +#config__manager div.success,#config__manager div.error,#config__manager div.info{background-position:0.5em;padding:0.5em;text-align:center;} +#config__manager fieldset{margin:1em;width:auto;margin-bottom:2em;background-color:#dee7ec;color:#000;padding:0 1em;} +#config__manager legend{font-size:1.25em;} +#config__manager form{}#config__manager table{margin:1em 0;width:100%;}#config__manager fieldset td{text-align:left;} +#config__manager fieldset td.value{width:31em;}#config__manager td.label{padding:0.8em 0 0.6em 1em;vertical-align:top; +}#config__manager td.label label{clear:left;display:block;} +#config__manager td.label img{padding:0 10px;vertical-align:middle;float:right;} +#config__manager td.label span.outkey{font-size:70%;margin-top:-1.7em;margin-left:-1em;display:block;background-color:#fff;color:#666;float:left;padding:0 0.1em;position:relative;z-index:1;} +#config__manager td input.edit{width:30em;}#config__manager td .input{width:30.8em;} +#config__manager td select.edit{}#config__manager td textarea.edit{width:27.5em;height:4em;} +#config__manager tr .input,#config__manager tr input,#config__manager tr textarea,#config__manager tr select{background-color:#fff;color:#000;} +#config__manager tr.default .input,#config__manager tr.default input,#config__manager tr.default textarea,#config__manager tr.default select,#config__manager .selectiondefault{background-color:#cdf;color:#000;} +#config__manager tr.protected .input,#config__manager tr.protected input,#config__manager tr.protected textarea,#config__manager tr.protected select,#config__manager tr.protected .selection{background-color:#fcc!important;color:#000 !important;} +#config__manager td.error{background-color:red;color:#000;}#config__manager .selection{width:14.8em;float:left;margin:0 0.3em 2px 0;}#config__manager .selection label{float:right;width:14em;font-size:90%;} +* html #config__manager .selection label{padding-top:2px;} +#config__manager .selection input.checkbox{padding-left:0.7em;} +#config__manager .other{clear:both;padding-top:0.5em;} +#config__manager .other label{padding-left:2px;font-size:90%;}.dokuwiki div.plugin_translation{float:right;font-size:95%;} +.dokuwiki div.plugin_translation ul{display:inline;padding:0;margin:0;} +.dokuwiki div.plugin_translation ul li{float:left;list-style-type:none;padding:0;margin:0;} +.dokuwiki div.plugin_translation ul li a.wikilink1:link,.dokuwiki div.plugin_translation ul li a.wikilink1:hover,.dokuwiki div.plugin_translation ul li a.wikilink1:active,.dokuwiki div.plugin_translation ul li a.wikilink1:visited{background-color:#000080;color:#fff !important;text-decoration:none;padding:0 0.2em;margin:0.1em 0.2em;border:none !important;} +.dokuwiki div.plugin_translation ul li a.wikilink2:link,.dokuwiki div.plugin_translation ul li a.wikilink2:hover,.dokuwiki div.plugin_translation ul li a.wikilink2:active,.dokuwiki div.plugin_translation ul li a.wikilink2:visited{background-color:#808080;color:#fff !important;text-decoration:none;padding:0 0.2em;margin:0.1em 0.2em;border:none !important;} +.dokuwiki div.plugin_translation ul li a img{opacity:0.5;border:0;} +.dokuwiki div.plugin_translation ul li a.wikilink2 img{}.dokuwiki div.plugin_translation span.curid a img{opacity:1.0;height:15px;} +.dokuwiki div.plugin_translation ul li a:hover img{opacity:1.0;height:15px;}#user__manager tr.disabled{color:#6f6f6f;background:#e4e4e4;} +#user__manager tr.user_info{vertical-align:top;} +#user__manager div.edit_user{width:46%;float:left;}#user__manager table{margin-bottom:1em;}#user__manager input.button[disabled]{color:#ccc!important;border-color:#ccc!important;}div.dokuwiki div.newentry_form{clear:both;text-align:center;margin-bottom:1em;} +div.dokuwiki #blog__newentry_form input.edit{width:95%;}div.dokuwiki tr.draft,div.dokuwiki div.draft{opacity:0.5;} +div.dokuwiki div.autoarchive_selector ul{list-style-type:none;clear:left;margin:0 0.5em 0 0;} +div.dokuwiki div.autoarchive_selector ul div.li{float:left;margin:0 1em 0 0;} +div.dokuwiki div.autoarchive_selector ul ul{float:left;clear:none;}div.dokuwiki div.autoarchive_selector ul ul div.li{margin:0;}div#acl_manager div#acl__tree{font-size:90%;width:25%;height:300px;float:left;overflow:auto;border:1px solid #8cacbb;text-align:left;} +div#acl_manager div#acl__tree a.cur{background-color:#ff9;font-weight:bold;} +div#acl_manager div#acl__tree ul{list-style-type:none;margin:0;padding:0;}div#acl_manager div#acl__tree li{padding-left:1em;}div#acl_manager div#acl__tree ul img{margin-right:0.25em;cursor:pointer;} +div#acl_manager div#acl__detail{width:73%;height:300px;float:right;overflow:auto;} +div#acl_manager div#acl__detail fieldset{width:90%;} +div#acl_manager div#acl__detail div#acl__user{border:1px solid #8cacbb;padding:0.5em;margin-bottom:0.6em;} +div#acl_manager table.inline{width:100%;margin:0;} +div#acl_manager .aclgroup{background:transparent url(media/img/group.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;} +div#acl_manager .acluser{background:transparent url(media/img/user.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;} +div#acl_manager .aclpage{background:transparent url(media/img/page.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;} +div#acl_manager .aclns{background:transparent url(media/img/ns.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;} +div#acl_manager label.disabled{color:#666!important;} +#acl_manager label{text-align:left;font-weight:normal;display:inline;} +#acl_manager table{margin-left:10%;width:80%;}#acl_manager table tr{background-color:inherit;} +#acl_manager table tr:hover{background-color:#dee7ec;} + + +a.interwiki{background:transparent url(/lib/images/interwiki.png) 0px 1px no-repeat;padding-left:16px;} +a.iw_wp{background-image:url(/media/img/wp.gif)} +a.iw_wpde{background-image:url(/media/img/wpde.gif)} +a.iw_wpmeta{background-image:url(/media/img/wpmeta.gif)} +a.iw_doku{background-image:url(/media/img/doku.gif)} +a.iw_dokubug{background-image:url(/media/img/dokubug.gif)} +a.iw_amazon{background-image:url(/media/img/amazon.gif)} +a.iw_amazon_de{background-image:url(/media/img/amazon.de.gif)} +a.iw_amazon_uk{background-image:url(/media/img/amazon.uk.gif)} +a.iw_phpfn{background-image:url(/media/img/phpfn.gif)} +a.iw_coral{background-image:url(/media/img/coral.gif)} +a.iw_sb{background-image:url(/media/img/sb.gif)} +a.iw_google{background-image:url(/media/img/google.gif)} +a.iw_meatball{background-image:url(/media/img/meatball.gif)} +a.iw_wiki{background-image:url(/media/img/wiki.gif)} +a.mediafile{background:transparent url(/media/img/file.png) 0px 1px no-repeat;padding-left:18px;padding-bottom:1px;}a.mf_jpg{background-image:url(/media/img/jpg.png)}a.mf_jpeg{background-image:url(/media/img/jpeg.png)}a.mf_gif{background-image:url(/media/img/gif.png)}a.mf_png{background-image:url(/media/img/png.png)}a.mf_tgz{background-image:url(/media/img/tgz.png)}a.mf_tar{background-image:url(/media/img/tar.png)}a.mf_gz{background-image:url(/media/img/gz.png)}a.mf_bz2{background-image:url(/media/img/bz2.png)} +a.mf_zip{background-image:url(/media/img/zip.png)}a.mf_rar{background-image:url(/media/img/rar.png)}a.mf_pdf{background-image:url(/media/img/pdf.png)}a.mf_ps{background-image:url(/media/img/ps.png)}a.mf_doc{background-image:url(/media/img/doc.png)}a.mf_xls{background-image:url(/media/img/xls.png)}a.mf_ppt{background-image:url(/media/img/ppt.png)}a.mf_rtf{background-image:url(/media/img/rtf.png)}a.mf_swf{background-image:url(/media/img/swf.png)}a.mf_rpm{background-image:url(/media/img/rpm.png)}a.mf_deb{background-image:url(/media/img/deb.png)}a.mf_sxw{background-image:url(/media/img/sxw.png)}a.mf_sxc{background-image:url(/media/img/sxc.png)}a.mf_sxi{background-image:url(/media/img/sxi.png)}a.mf_sxd{background-image:url(/media/img/sxd.png)}a.mf_odc{background-image:url(/media/img/odc.png)}a.mf_odf{background-image:url(/media/img/odf.png)}a.mf_odg{background-image:url(/media/img/odg.png)} +a.mf_odi{background-image:url(/media/img/odi.png)}a.mf_odp{background-image:url(/media/img/odp.png)}a.mf_ods{background-image:url(/media/img/ods.png)}a.mf_odt{background-image:url(/media/img/odt.png)}body{margin:0px;padding:0px;background-color:white;color:black;font-size:12px;font-family:Verdana,Helvetica,"Lucida Grande",Lucida,Arial,sans-serif;font-family:sans-serif;font-size:99,96%;font-size-adjust:none;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;}hr{border-width:0px;border-bottom:1px #aaa dotted;}img{border:none;}form{margin:0px;padding:0px;border:none;display:inline;background:transparent;}ul li{margin:5px;}textarea{font-family:monospace;}table{margin:0.5em 0;border-collapse:collapse;}td{padding:0.25em;border:1pt solid #ADB9CC;}a{color:#3465a4;text-decoration:none;}a:hover{text-decoration:underline;} +a.wikilink2{color:#a40000 !important;}.dokuwiki h1 a,.dokuwiki h2 a,.dokuwiki h3 a,.dokuwiki h4 a,.dokuwiki h5 a,.dokuwiki a.nolink{color:#000 !important;text-decoration:none !important;} +option{border:0px none #fff;}strong.highlight{background-color:#fc9;padding:1pt;}#pagebottom{clear:both;}hr{height:1px;color:#c0c0c0;background-color:#c0c0c0;border:none;margin:.2em 0 .2em 0;}pre{padding:0.5em;font-family:courier,monospace;border:1px solid #c0c0c0;background:#F0ECE6;white-space:pre;white-space:pre-wrap;word-wrap:break-word;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;}.invisible{margin:0px;border:0px;padding:0px;height:0px;visibility:hidden;}.left{float:left !important;}.right{float:right !important;}.center{text-align:center;}div#body-wrapper{padding:40px 40px 10px 40px;font-size:127%;} +div#content{margin-top:-20px;padding:0;font-size:14px;color:black;line-height:1.5em;}h1,h2,h3,h4,h5,h6{background:transparent none repeat scroll 0 0;border-bottom:1px solid #aaa;color:black;font-weight:normal;margin:0;padding:0;padding-bottom:0.17em;padding-top:0.5em;}h1{font-size:188%;line-height:1.2em;margin-bottom:0.1em;padding-bottom:0;}h2{font-size:150%;}h3,h4,h5,h6{border-bottom:none;font-weight:bold;}h3{font-size:132%;}h4{font-size:116%;}h5{font-size:100%;}h6{font-size:80%;}ul#page-actions{float:right;margin:10px 10px 0 10px;padding:6px;color:black;background-color:#ececec;list-style-type:none;-moz-border-radius:5px;}ul#user-actions{padding:5px;margin:0;display:inline;color:black;background-color:#ececec;list-style-type:none;-moz-border-radius:3px;}ul#page-actions li,ul#user-actions li{display:inline;}ul#page-actions a,ul#user-actions a{text-decoration:none;color:black;display:inline;margin:0 3px;padding:2px 0px 2px 18px;} +ul#page-actions a:hover,ul#page-actions a:focus,ul#user-actions a:hover,ul#user-actions a:focus{text-decoration:underline;}.hidden{display:none;}a.urlextern{color:#36B;background:transparent url(/media/img/external-10.2.png) no-repeat scroll right center;padding:0 13px 0 0;}a[href^="http://www.pyload.org"]:after,a.noextlink:after{background:none;padding:0;}a.action.index{background:transparent url(/media/img/wiki-tools-index.png) 0px 1px no-repeat;}a.action.recent{background:transparent url(/media/img/wiki-tools-recent.png) 0px 1px no-repeat;}a.logout{background:transparent url(/media/img/user-actions-logout.png) 0px 1px no-repeat;} +a.admin{background:transparent url(/media/img/user-actions-admin.png) 0px 1px no-repeat;}a.profile{background:transparent url(/media/img/user-actions-profile.png) 0px 1px no-repeat;}a.create,a.edit{background:transparent url(/media/img/page-tools-edit.png) 0px 1px no-repeat;}a.source,a.show{background:transparent url(/media/img/page-tools-source.png) 0px 1px no-repeat;}a.revisions{background:transparent url(/media/img/page-tools-revisions.png) 0px 1px no-repeat;}a.subscribe,a.unsubscribe{background:transparent url(/media/img/page-tools-subscribe.png) 0px 1px no-repeat;}a.backlink{background:transparent url(/media/img/page-tools-backlinks.png) 0px 1px no-repeat;}#head-panel{background:#525252 url(/media/img/head_bg1.png) bottom left repeat-x;}#head-panel h1{display:none;margin:0;text-decoration:none;padding-top:0.8em;padding-left:3.3em;font-size:2.6em;color:#eeeeec;}#head-panel #head-logo{float:left;margin:5px 0 -15px 5px;padding:0;overflow:visible;}#head-menu{background:transparent url(/media/img/tabs-border-bottom.png) 0 100% repeat-x;width:100%;float:left;margin:0;padding:0;padding-top:0.8em;} +#head-menu ul{list-style:none;margin:0 1em 0 2em;}#head-menu ul li{float:left;margin:0;margin-left:0.3em;font-size:14px;margin-bottom:4px;}#head-menu ul li.selected,#head-menu ul li:hover{margin-bottom:0px;}#head-menu ul li a img{height:22px;width:22px;vertical-align:middle;}#head-menu ul li a,#head-menu ul li a:link{float:left;text-decoration:none;color:#555;background:#eaeaea url(/media/img/tab-background.png) 0 100% repeat-x;padding:3px 7px 3px 7px;border:2px solid #ccc;border-bottom:0px solid transparent;padding-bottom:3px;-moz-border-radius:5px;}#head-menu ul li a:hover,#head-menu ul li a:focus{color:#111;padding-bottom:7px;border-bottom:0px none transparent;outline:none;-moz-border-radius-bottomright:0px;-moz-border-radius-bottomleft:0px;}#head-menu ul li a:focus{margin-bottom:-4px;}#head-menu ul li.selected a{color:#3566A5;background:#fff;padding-bottom:7px;border-bottom:0px none transparent;-moz-border-radius-bottomright:0px;-moz-border-radius-bottomleft:0px;}#head-menu ul li.selected a:hover,#head-menu ul li.selected a:focus{color:#111;}div#head-search-and-login{float:right;margin:0 1em 0 0;background-color:#222;padding:4px;color:white;-moz-border-radius-bottomright:6px;-moz-border-radius-bottomleft:6px;}div#head-search-and-login form{display:inline;padding:0 3px;}div#head-search-and-login form input{border:2px solid #888;background:#eee;font-size:14px;padding:2px;-moz-border-radius:3px;}div#head-search-and-login form input:focus{background:#fff;}#head-search{font-size:14px;}#head-username,#head-password{width:80px;font-size:14px;}#pageinfo{clear:both;color:#888;padding:0.6em 0;margin:0;}#foot{font-style:normal;color:#888;text-align:center;}#foot a{color:#aaf;}#foot img{vertical-align:middle;}ul.toc{padding:0;padding-left:20px;margin-left:0;margin-right:10px;list-style:none;}ul.toc li{list-style:circle;}ul.toc li a{text-decoration:none;color:black;}ul.toc li a:hover{text-decoration:underline;}div.toc{border:1px dotted #888;background:#f0f0f0;margin:1em 0 1em 1em;float:right;font-size:95%;}div.toc .tocheader{font-weight:bold;margin:0.5em 1em;}div.toc ol{margin:1em 0.5em 1em 1em;padding:0;}div.toc ol li{margin:0;padding:0;margin-left:1em;}div.toc ol ol{margin:0.5em 0.5em 0.5em 1em;padding:0;}div.recentchanges table{clear:both;}div#editor-help{font-size:90%;border:1px dotted #888;padding:0ex 1ex 1ex 1ex;background:#f7f6f2;}div#preview{margin-top:1em;}label.block{display:block;text-align:right;font-weight:bold;}label.simple{display:block;text-align:left;font-weight:normal;}label.block input.edit{width:50%;}fieldset{width:300px;text-align:center;padding:0.5em;margin:auto;}div.editor{margin:0 0 0 0;}table{margin:0.5em 0;border-collapse:collapse;}td{padding:0.25em;border:1pt solid #ADB9CC;}td p{margin:0;padding:0;}.u{text-decoration:underline;}.footnotes ul{padding:0 2em;margin:0 0 1em;}.footnotes li{list-style:none;}.recentchanges p{margin:0.25em;}.recentchanges td{vertical-align:top;border:none;border-bottom:1pt solid #F0ECE6;background:#F7F6F2;}.rcdaybreak td{background:#729fcf;border:none;}.rcdaybreak td a{font-size:0.88em;}.rcicon1,.rcicon2{text-align:center;}.rcpagelink{width:33%;}.rctime{font-size:0.88em;white-space:nowrap;}.rceditor{white-space:nowrap;font-size:0.88em;}.rccomment{width:66%;color:gray;font-size:0.88em;}.rcrss{float:right;}.recentchanges[dir="rtl"] .rcrss{float:left;}.userpref table,.userpref td{border:none;}div.codearea{margin:0.5em 0;padding:0;border:1pt solid #AEBDCC;background-color:#F3F5F7;color:black;}div.codearea pre{margin:0;padding:10pt;border:none;}a.codenumbers{margin:0 10pt;font-size:0.85em;color:gray;}div.codearea pre span.LineNumber{color:gray;}div.codearea pre span.ID{color:#000;}div.codearea pre span.Operator{color:#0000c0;}div.codearea pre span.Char{color:#004080;}div.codearea pre span.Comment{color:#008000;}div.codearea pre span.Number{color:#0080c0;}div.codearea pre span.String{color:#004080;}div.codearea pre span.SPChar{color:#0000c0;}div.codearea pre span.ResWord{color:#a00000;}div.codearea pre span.ConsWord{color:#008080;font-weight:bold;}div.codearea pre span.Error{color:#ff8080;border:solid 1.5pt #f00;}div.codearea pre span.ResWord2{color:#0080ff;font-weight:bold;}div.codearea pre span.Special{color:#00f;}div.codearea pre span.Preprc{color:#803999;}#message{clear:both;padding:5px 10px;background-color:#eee;border-bottom:2px solid #ccc;}#message p{margin:5px 0;padding:0;font-weight:bold;}#message div.buttons{font-weight:normal;}.diff{width:99%;}.diff-title{background-color:#C0C0C0;}.searchresult dd span{font-weight:bold;}.diff{width:100%;border:none;}.diff-blockheader{font-weight:bold;background:#e5e5e5;font-size:1.2em;border-top:2px solid #444;padding:5px;}.diff th{font-size:120%;width:50%;font-weight:normal;text-align:left;padding-bottom:3px;}.diff td{font-family:monospace;font-size:100%;border:none;}.diff-addedline{background-color:#dfd;}.diff-deletedline{background-color:#ffb;}.diff-context{color:#888;}.diff-addedline{background-color:#E0FFE0;vertical-align:sub;}.diff-deletedline{background-color:#FFFFE0;background-color:#f4cece;vertical-align:sub;} +.diff-addedline strong{background-color:#80FF80;background-color:#8ae234;} +.diff-deletedline strong{background-color:#FFFF80;background-color:#ef2929;background-color:#d78383;} + + + +.box{ background:url(/media/img/progress-bar-back.gif) right center no-repeat; width:200px; height:20px; float:left; } +.perc{ background:url(/media/img/progress-bar.gif) right center no-repeat; height:20px; } +.boxtext{ font-family:tahoma, arial, sans-serif; font-size:11px; color:#000; float:none; padding:3px 0 0 10px; } +.statusbutton{width:32px;height:32px;float:left;margin-left:-32px;margin-right:5px;opacity:0;cursor:pointer} + +.dlsize{float:left; padding-right: 8px;} +.dlspeed{float:left; padding-right: 8px;}
\ No newline at end of file diff --git a/module/web/static/window.css b/module/web/media/css/window.css index aaccae082..aaccae082 100644 --- a/module/web/static/window.css +++ b/module/web/media/css/window.css diff --git a/module/web/static/default/Button-Add-grey.png b/module/web/media/img/Button-Add-grey.pngBinary files differ index 6659e230e..6659e230e 100644 --- a/module/web/static/default/Button-Add-grey.png +++ b/module/web/media/img/Button-Add-grey.png diff --git a/module/web/static/default/Button-Add.png b/module/web/media/img/Button-Add.pngBinary files differ index 602da4131..602da4131 100644 --- a/module/web/static/default/Button-Add.png +++ b/module/web/media/img/Button-Add.png diff --git a/module/web/static/default/Button-Pause-grey.png b/module/web/media/img/Button-Pause-grey.pngBinary files differ index d1017e974..d1017e974 100644 --- a/module/web/static/default/Button-Pause-grey.png +++ b/module/web/media/img/Button-Pause-grey.png diff --git a/module/web/static/default/Button-Pause.png b/module/web/media/img/Button-Pause.pngBinary files differ index 68f3ffc3a..68f3ffc3a 100644 --- a/module/web/static/default/Button-Pause.png +++ b/module/web/media/img/Button-Pause.png diff --git a/module/web/static/default/Button-Play-grey.png b/module/web/media/img/Button-Play-grey.pngBinary files differ index 9f44c2289..9f44c2289 100644 --- a/module/web/static/default/Button-Play-grey.png +++ b/module/web/media/img/Button-Play-grey.png diff --git a/module/web/static/default/Button-Play.png b/module/web/media/img/Button-Play.pngBinary files differ index 1ce1ed913..1ce1ed913 100644 --- a/module/web/static/default/Button-Play.png +++ b/module/web/media/img/Button-Play.png diff --git a/module/web/static/window/big_button.gif b/module/web/media/img/big_button.gifBinary files differ index 7680490ea..7680490ea 100644 --- a/module/web/static/window/big_button.gif +++ b/module/web/media/img/big_button.gif diff --git a/module/web/static/window/big_button_over.gif b/module/web/media/img/big_button_over.gifBinary files differ index 2e3ee10d2..2e3ee10d2 100644 --- a/module/web/static/window/big_button_over.gif +++ b/module/web/media/img/big_button_over.gif diff --git a/module/web/static/window/body.png b/module/web/media/img/body.pngBinary files differ index 7ff1043e0..7ff1043e0 100644 --- a/module/web/static/window/body.png +++ b/module/web/media/img/body.png diff --git a/module/web/static/window/closebtn.gif b/module/web/media/img/closebtn.gifBinary files differ index 3e27e6030..3e27e6030 100644 --- a/module/web/static/window/closebtn.gif +++ b/module/web/media/img/closebtn.gif diff --git a/module/web/static/window/drag_corner.gif b/module/web/media/img/drag_corner.gifBinary files differ index befb1adf1..befb1adf1 100644 --- a/module/web/static/window/drag_corner.gif +++ b/module/web/media/img/drag_corner.gif diff --git a/module/web/static/window/full.png b/module/web/media/img/full.pngBinary files differ index fea52af76..fea52af76 100644 --- a/module/web/static/window/full.png +++ b/module/web/media/img/full.png diff --git a/module/web/static/default/head-login.png b/module/web/media/img/head-login.pngBinary files differ index b59b7cbbf..b59b7cbbf 100644 --- a/module/web/static/default/head-login.png +++ b/module/web/media/img/head-login.png diff --git a/module/web/static/default/head-menu-development.png b/module/web/media/img/head-menu-development.pngBinary files differ index 8ef08e2e5..8ef08e2e5 100644 --- a/module/web/static/default/head-menu-development.png +++ b/module/web/media/img/head-menu-development.png diff --git a/module/web/static/default/head-menu-download.png b/module/web/media/img/head-menu-download.pngBinary files differ index 98c5da9db..98c5da9db 100644 --- a/module/web/static/default/head-menu-download.png +++ b/module/web/media/img/head-menu-download.png diff --git a/module/web/static/default/head-menu-home.png b/module/web/media/img/head-menu-home.pngBinary files differ index 9d62109aa..9d62109aa 100644 --- a/module/web/static/default/head-menu-home.png +++ b/module/web/media/img/head-menu-home.png diff --git a/module/web/static/default/head-menu-index.png b/module/web/media/img/head-menu-index.pngBinary files differ index 44d631064..44d631064 100644 --- a/module/web/static/default/head-menu-index.png +++ b/module/web/media/img/head-menu-index.png diff --git a/module/web/static/default/head-menu-news.png b/module/web/media/img/head-menu-news.pngBinary files differ index 43950ebc9..43950ebc9 100644 --- a/module/web/static/default/head-menu-news.png +++ b/module/web/media/img/head-menu-news.png diff --git a/module/web/static/default/head-menu-recent.png b/module/web/media/img/head-menu-recent.pngBinary files differ index fc9b0497f..fc9b0497f 100644 --- a/module/web/static/default/head-menu-recent.png +++ b/module/web/media/img/head-menu-recent.png diff --git a/module/web/static/default/head-menu-wiki.png b/module/web/media/img/head-menu-wiki.pngBinary files differ index 07cf0102d..07cf0102d 100644 --- a/module/web/static/default/head-menu-wiki.png +++ b/module/web/media/img/head-menu-wiki.png diff --git a/module/web/static/default/head-search-noshadow.png b/module/web/media/img/head-search-noshadow.pngBinary files differ index aafdae015..aafdae015 100644 --- a/module/web/static/default/head-search-noshadow.png +++ b/module/web/media/img/head-search-noshadow.png diff --git a/module/web/static/default/head_bg1.png b/module/web/media/img/head_bg1.pngBinary files differ index f2848c3cc..f2848c3cc 100644 --- a/module/web/static/default/head_bg1.png +++ b/module/web/media/img/head_bg1.png diff --git a/module/web/static/default/page-tools-backlinks.png b/module/web/media/img/page-tools-backlinks.pngBinary files differ index 3eb6a9ce3..3eb6a9ce3 100644 --- a/module/web/static/default/page-tools-backlinks.png +++ b/module/web/media/img/page-tools-backlinks.png diff --git a/module/web/static/default/page-tools-edit.png b/module/web/media/img/page-tools-edit.pngBinary files differ index 188e1c12b..188e1c12b 100644 --- a/module/web/static/default/page-tools-edit.png +++ b/module/web/media/img/page-tools-edit.png diff --git a/module/web/static/default/page-tools-revisions.png b/module/web/media/img/page-tools-revisions.pngBinary files differ index 5c3b8587f..5c3b8587f 100644 --- a/module/web/static/default/page-tools-revisions.png +++ b/module/web/media/img/page-tools-revisions.png diff --git a/module/web/static/default/progress-bar-back.gif b/module/web/media/img/progress-bar-back.gifBinary files differ index 0c8f68211..0c8f68211 100644 --- a/module/web/static/default/progress-bar-back.gif +++ b/module/web/media/img/progress-bar-back.gif diff --git a/module/web/static/default/progress-bar.gif b/module/web/media/img/progress-bar.gifBinary files differ index 746f77175..746f77175 100644 --- a/module/web/static/default/progress-bar.gif +++ b/module/web/media/img/progress-bar.gif diff --git a/module/web/static/default/pyload-logo-edited3.5-new-font-small.png b/module/web/media/img/pyload-logo-edited3.5-new-font-small.pngBinary files differ index 2443cd8b1..2443cd8b1 100644 --- a/module/web/static/default/pyload-logo-edited3.5-new-font-small.png +++ b/module/web/media/img/pyload-logo-edited3.5-new-font-small.png diff --git a/module/web/static/default/tab-background.png b/module/web/media/img/tab-background.pngBinary files differ index 29a5d1991..29a5d1991 100644 --- a/module/web/static/default/tab-background.png +++ b/module/web/media/img/tab-background.png diff --git a/module/web/static/default/tabs-border-bottom.png b/module/web/media/img/tabs-border-bottom.pngBinary files differ index 02440f428..02440f428 100644 --- a/module/web/static/default/tabs-border-bottom.png +++ b/module/web/media/img/tabs-border-bottom.png diff --git a/module/web/static/default/user-actions-logout.png b/module/web/media/img/user-actions-logout.pngBinary files differ index 0010931e2..0010931e2 100644 --- a/module/web/static/default/user-actions-logout.png +++ b/module/web/media/img/user-actions-logout.png diff --git a/module/web/static/default/user-actions-profile.png b/module/web/media/img/user-actions-profile.pngBinary files differ index 46573fff6..46573fff6 100644 --- a/module/web/static/default/user-actions-profile.png +++ b/module/web/media/img/user-actions-profile.png diff --git a/module/web/static/default/home.js b/module/web/media/js/home.js index 025dcfcc7..025dcfcc7 100644 --- a/module/web/static/default/home.js +++ b/module/web/media/js/home.js diff --git a/module/web/static/mootools-1.2.3-core.js b/module/web/media/js/mootools-1.2.3-core.js index 25f1f9d03..25f1f9d03 100644 --- a/module/web/static/mootools-1.2.3-core.js +++ b/module/web/media/js/mootools-1.2.3-core.js diff --git a/module/web/static/mootools-1.2.3.1-more.js b/module/web/media/js/mootools-1.2.3.1-more.js index f3e4b4121..f3e4b4121 100644 --- a/module/web/static/mootools-1.2.3.1-more.js +++ b/module/web/media/js/mootools-1.2.3.1-more.js diff --git a/module/web/static/default/status.js b/module/web/media/js/status.js index 3923e80ca..3923e80ca 100644 --- a/module/web/static/default/status.js +++ b/module/web/media/js/status.js diff --git a/module/web/pyload.db b/module/web/pyload.dbBinary files differ new file mode 100644 index 000000000..8d34ef89c --- /dev/null +++ b/module/web/pyload.db diff --git a/module/web/pyload/__init__.py b/module/web/pyload/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/module/web/pyload/__init__.py diff --git a/module/web/pyload/admin.py b/module/web/pyload/admin.py new file mode 100644 index 000000000..40a96afc6 --- /dev/null +++ b/module/web/pyload/admin.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/module/web/pyload/models.py b/module/web/pyload/models.py new file mode 100644 index 000000000..293c01109 --- /dev/null +++ b/module/web/pyload/models.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from django.db import models +#from django.contrib.auth.models.User import User as UserProfile +# Create your models here. + + +class Perm(models.Model): +    """ extended pyLoad user Profile """ +     +    #user = models.ForeignKey(UserProfile, unique=True) +    #template = models.CharField(maxlength=30) +     +    class Meta: +        permissions = ( +            ("can_see_dl", "Can see Downloads"), +            ("can_add", "Can add Downloads"), +            ("can_delete", "Can delete Downloads"), +            ("can_download", "Can download Files"), +            ("can_see_logs", "Can see logs"), +            ("can_change_status", "Can change status"), +        )
\ No newline at end of file diff --git a/module/web/pyload/tests.py b/module/web/pyload/tests.py new file mode 100644 index 000000000..2247054b3 --- /dev/null +++ b/module/web/pyload/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): +    def test_basic_addition(self): +        """ +        Tests that 1 + 1 always equals 2. +        """ +        self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/module/web/pyload/urls.py b/module/web/pyload/urls.py new file mode 100644 index 000000000..9c7942492 --- /dev/null +++ b/module/web/pyload/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('', +                       (r'^login/$', 'pyload.views.login'), +                       (r'^home/$', 'pyload.views.home'), +                       (r'^test/$', 'pyload.views.home'), +) diff --git a/module/web/pyload/views.py b/module/web/pyload/views.py new file mode 100644 index 000000000..c42511ede --- /dev/null +++ b/module/web/pyload/views.py @@ -0,0 +1,80 @@ +# Create your views here. +from django.http import HttpResponse +from django.http import HttpResponseRedirect +from django.http import HttpResponseGone +from django.conf import settings +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.contrib.auth.decorators import login_required +from os.path import join + + +def check_server(function): +    def _dec(view_func): +        def _view(request, *args, **kwargs): +            try: +                version = settings.PYLOAD.get_server_version() +                return view_func(request, *args, **kwargs) +            except Exception, e: +                return base(request, messages=['Can\'t connect to pyLoad. Please check your configuration and make sure pyLoad is running.',str(e)]) +         +        _view.__name__ = view_func.__name__ +        _view.__dict__ = view_func.__dict__ +        _view.__doc__ = view_func.__doc__ + +        return _view + +    if function is None: +        return _dec +    else: +        return _dec(function) +         +         +def permission(perm): +    def _dec(view_func): +        def _view(request, *args, **kwargs): +            if request.user.has_perm(perm): +                return view_func(request, *args, **kwargs) +            else: +                return base(request, messages=['You don\'t have permission to view this page.']) +         +        _view.__name__ = view_func.__name__ +        _view.__dict__ = view_func.__dict__ +        _view.__doc__ = view_func.__doc__ + +        return _view + +    return _dec + + +def base(request, messages): +    return render_to_response(join(settings.TEMPLATE,'base.html'), {'messages': messages},RequestContext(request)) + +@login_required +#@permission('perm.permissions.can_see_dl') @TODO: Permissions not working :( +@check_server +def home(request): +    return render_to_response(join(settings.TEMPLATE,'home.html'), RequestContext(request)) +     + +@login_required +#@permission('pyload.perm.can_see_dl') +@check_server +def queue(request): +    return render_to_response(join(settings.TEMPLATE,'queue.html'), RequestContext(request)) + + +@login_required +#@permission('pyload.user.can_download') +@check_server +def downloads(request): +    return render_to_response(join(settings.TEMPLATE,'downloads.html'), RequestContext(request)) + + +@login_required +#@permission('pyload.user.can_see_logs') +@check_server +def logs(request): +    return render_to_response(join(settings.TEMPLATE,'logs.html'), RequestContext(request)) +     +    
\ No newline at end of file diff --git a/module/web/settings.py b/module/web/settings.py new file mode 100644 index 000000000..0dc86d699 --- /dev/null +++ b/module/web/settings.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +# Django settings for pyload project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +import ConfigParser +import os.path +from os import chdir +from os.path import dirname +from os.path import abspath +from os import sep +import xmlrpclib + +SERVER_VERSION = "0.3" + +PROJECT_DIR = os.path.dirname(__file__) + +#chdir(dirname(abspath(__file__)) + sep) +config = ConfigParser.SafeConfigParser() +config.read(os.path.join(PROJECT_DIR,"..","..","config")) + +ssl = "" + +if config.get("ssl", "activated") == "True": +    ssl = "s" + +server_url = "http%s://%s:%s@%s:%s/" % ( +                                        ssl, +                                        config.get("remote", "username"), +                                        config.get("remote", "password"), +                                        config.get("remote", "listenaddr"), +                                        config.get("remote", "port") +                                        ) + +PYLOAD = xmlrpclib.ServerProxy(server_url, allow_none=True) + +TEMPLATE = config.get('webinterface','template') + +ADMINS = ( +          # ('Your Name', 'your_email@domain.com'), +          ) + +MANAGERS = ADMINS + +DATABASE_ENGINE = 'sqlite3'           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. +DATABASE_NAME = 'pyload.db'             # Or path to database file if using sqlite3. +DATABASE_USER = ''             # Not used with sqlite3. +DATABASE_PASSWORD = ''         # Not used with sqlite3. +DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3. +DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3. + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = os.path.join(PROJECT_DIR, "media/") + + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" + +#MEDIA_URL = 'http://localhost:8000/media' +MEDIA_URL = '/media/' +#MEDIA_URL = os.path.join(PROJECT_DIR, "media/") + +LOGIN_REDIRECT_URL = "/" + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/admin/' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '+u%%1t&c7!e$0$*gu%w2$@to)h0!&x-r*9e+-=wa4*zxat%x^t' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( +                    'django.template.loaders.filesystem.load_template_source', +                    'django.template.loaders.app_directories.load_template_source', +                    #     'django.template.loaders.eggs.load_template_source', +                    ) + +MIDDLEWARE_CLASSES = ( +                      'django.middleware.common.CommonMiddleware', +                      'django.contrib.sessions.middleware.SessionMiddleware', +                      'django.contrib.auth.middleware.AuthenticationMiddleware', +                      ) + +ROOT_URLCONF = 'urls' + +TEMPLATE_DIRS = ( +                 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". +                 # Always use forward slashes, even on Windows. +                 # Don't forget to use absolute paths, not relative paths. +                 os.path.join(PROJECT_DIR, "templates"), +                 ) + +INSTALLED_APPS = ( +                  'django.contrib.auth', +                  'django.contrib.contenttypes', +                  'django.contrib.sessions', +                  #'django.contrib.sites', +                  'django.contrib.admin', +                  'pyload', +                  'ajax', +                  ) + + +AUTH_PROFILE_MODULE = 'pyload.User' +LOGIN_URL = '/login'
\ No newline at end of file diff --git a/module/web/static/default.css b/module/web/static/default.css deleted file mode 100644 index fd2e85eb9..000000000 --- a/module/web/static/default.css +++ /dev/null @@ -1,189 +0,0 @@ -a.interwiki{background:transparent url(static/default/interwiki.png) 0px 1px no-repeat;padding-left:16px;} -a.iw_wp{background-image:url(static/default/interwiki/wp.gif)} -a.iw_wpde{background-image:url(static/default/interwiki/wpde.gif)} -a.iw_wpmeta{background-image:url(static/default/interwiki/wpmeta.gif)} -a.iw_doku{background-image:url(static/default/interwiki/doku.gif)} -a.iw_dokubug{background-image:url(static/default/interwiki/dokubug.gif)} -a.iw_amazon{background-image:url(static/default/interwiki/amazon.gif)} -a.iw_amazon_de{background-image:url(static/default/interwiki/amazon.de.gif)} -a.iw_amazon_uk{background-image:url(static/default/interwiki/amazon.uk.gif)} -a.iw_phpfn{background-image:url(static/default/interwiki/phpfn.gif)} -a.iw_coral{background-image:url(static/default/interwiki/coral.gif)} -a.iw_sb{background-image:url(static/default/interwiki/sb.gif)} -a.iw_google{background-image:url(static/default/interwiki/google.gif)} -a.iw_meatball{background-image:url(static/default/interwiki/meatball.gif)} -a.iw_wiki{background-image:url(static/default/interwiki/wiki.gif)} -a.mediafile{background:transparent url(static/default/file.png) 0px 1px no-repeat;padding-left:18px;padding-bottom:1px;} -a.mf_jpg{background-image:url(static/default/jpg.png)} -a.mf_jpeg{background-image:url(static/default/jpeg.png)} -a.mf_gif{background-image:url(static/default/gif.png)} -a.mf_png{background-image:url(static/default/png.png)} -a.mf_tgz{background-image:url(static/default/tgz.png)} -a.mf_tar{background-image:url(static/default/tar.png)} -a.mf_gz{background-image:url(static/default/gz.png)} -a.mf_bz2{background-image:url(static/default/bz2.png)} -a.mf_zip{background-image:url(static/default/zip.png)} -a.mf_rar{background-image:url(static/default/rar.png)} -a.mf_pdf{background-image:url(static/default/pdf.png)} -a.mf_ps{background-image:url(static/default/ps.png)} -a.mf_doc{background-image:url(static/default/doc.png)} -a.mf_xls{background-image:url(static/default/xls.png)} -a.mf_ppt{background-image:url(static/default/ppt.png)} -a.mf_rtf{background-image:url(static/default/rtf.png)} -a.mf_swf{background-image:url(static/default/swf.png)} -a.mf_rpm{background-image:url(static/default/rpm.png)} -a.mf_deb{background-image:url(static/default/deb.png)} -a.mf_sxw{background-image:url(static/default/sxw.png)} -a.mf_sxc{background-image:url(static/default/sxc.png)} -a.mf_sxi{background-image:url(static/default/sxi.png)} -a.mf_sxd{background-image:url(static/default/sxd.png)} -a.mf_odc{background-image:url(static/default/odc.png)} -a.mf_odf{background-image:url(static/default/odf.png)} -a.mf_odg{background-image:url(static/default/odg.png)}a.mf_odi{background-image:url(static/default/odi.png)} -a.mf_odp{background-image:url(static/default/odp.png)}a.mf_ods{background-image:url(static/default/ods.png)} -a.mf_odt{background-image:url(static/default/odt.png)}div.clearer{clear:both;line-height:0;height:0;overflow:hidden;} -div.no{display:inline;margin:0;padding:0;}.hidden{display:none;} -div.error{background:#fcc url(static/default/error.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #faa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;} -div.info{background:#ccf url(static/default/info.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #aaf;font-size:90%;margin:0;padding-left:3em;overflow:hidden;} -div.success{background:#cfc url(static/default/success.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #afa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;} -div.notify{background:#ffc url(static/default/notify.png) 0.5em 0px no-repeat;color:#000;border-bottom:1px solid #ffa;font-size:90%;margin:0;padding-left:3em;overflow:hidden;} -.medialeft{float:left;}.mediaright{float:right;} -.mediacenter{display:block;margin-left:auto;margin-right:auto;} -.leftalign{text-align:left;} -.centeralign{text-align:center;} -.rightalign{text-align:right;} -em.u{font-style:normal;text-decoration:underline;} -em em.u{font-style:italic;} -.code .br0{color:#6c6;} -.code .co1{color:#808080;font-style:italic;} -.code .co2{color:#808080;font-style:italic;} -.code .co3{color:#808080;} -.code .coMULTI{color:#808080;font-style:italic;} -.code .es0{color:#009;font-weight:bold;}.code .kw1{color:#b1b100;} -.code .kw2{color:#000;font-weight:bold;}.code .kw3{color:#006;} -.code .kw4{color:#933;}.code .kw5{color:#00f;}.code .me1{color:#060;}.code .me2{color:#060;} -.code .nu0{color:#c6c;}.code .re0{color:#00f;}.code .re1{color:#00f;}.code .re2{color:#00f;}.code .re3{color:#f33;font-weight:bold;}.code .re4{color:#099;}.code .st0{color:#f00;}.code .sy0{color:#6c6;} -div.dokuwiki table.pagelist,div.dokuwiki table.ul{border:0;padding:0;border-spacing:0;margin-bottom:1em;border-collapse:collapse;} -div.dokuwiki table.pagelist tr{border-top:1px solid #8cacbb;border-bottom:1px solid #8cacbb;} -div.dokuwiki table.pagelist th,div.dokuwiki table.pagelist td{padding:1px 1em 1px 0;} -div.dokuwiki table.ul th,div.dokuwiki table.ul td{padding:0 1em 0 0;} -div.dokuwiki table.ul ul{margin:0 0 0 1.5em;} -div.dokuwiki table.pagelist th,div.dokuwiki table.ul th{background-color:#dee7ec;} -div.dokuwiki th.page,div.dokuwiki th.date,div.dokuwiki th.user,div.dokuwiki th.desc,div.dokuwiki th.comments,div.dokuwiki th.linkbacks,div.dokuwiki th.tags,div.dokuwiki td.date,div.dokuwiki td.user,div.dokuwiki td.desc,div.dokuwiki td.comments,div.dokuwiki td.linkbacks,div.dokuwiki td.tags{color:#666;font-size:80%;} -div.dokuwiki td.date{text-align:right;}div.dokuwiki div.include div.secedit{float:right;margin-left:1em;margin-top:-18px;} -div.dokuwiki div.inclmeta{border-top:1px dotted #8cacbb;padding-top:0.2em;color:#666;font-size:80%;line-height:1.25;margin-top:0.5em;margin-bottom:2em;} -div.dokuwiki div.inclmeta a.permalink{background:transparent url(static/default/link.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;} -div.dokuwiki div.inclmeta abbr.published{background:transparent url(static/default/date.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;border-bottom:0;} -div.dokuwiki div.inclmeta span.author{background:transparent url(static/default/user.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;} -div.dokuwiki div.inclmeta span.comment{background:transparent url(static/default/comment.gif) 0px 1px no-repeat;padding:1px 0px 1px 16px;} -div.dokuwiki div.inclmeta div.tags{border-top:0;font-size:100%;float:right;clear:none;}#plugin__manager{}#plugin__manager h2{margin-left:0;} -#plugin__manager form{display:block;margin:0;padding:0;} -#plugin__manager legend{display:none;} -#plugin__manager fieldset{width:auto;} -#plugin__manager .button{margin:0;} -#plugin__manager p,#plugin__manager label{text-align:left;} -#plugin__manager .hidden{display:none;}#plugin__manager .new{background:#dee7ec;} -#plugin__manager input[disabled]{color:#ccc;border-color:#ccc;} -#plugin__manager .pm_menu,#plugin__manager .pm_info{margin-left:0;text-align:left;} -#plugin__manager .pm_menu{float:left;width:48%;} -#plugin__manager .pm_info{float:right;width:50%;} -#plugin__manager .common{}#plugin__manager .common form{} -#plugin__manager .common fieldset{margin:0;padding:0 0 1.0em 0;text-align:left;border:none;} -#plugin__manager .common label{padding:0 0 0.5em 0;} -#plugin__manager .common input{} -#plugin__manager .common input.edit{width:24em;margin:0.5em;} -#plugin__manager .common .button{} -#plugin__manager form.plugins{} -#plugin__manager .plugins fieldset{color:#000;background:#fff;text-align:right;border-top:none;border-right:none;border-left:none;} -#plugin__manager .plugins fieldset.protected{background:#fdd;color:#000;} -#plugin__manager .plugins fieldset.disabled{background:#e0e0e0;color:#a8a8a8;} -#plugin__manager .plugins .legend{color:#000;background:inherit;display:block;margin:0;padding:0;font-size:1em;line-height:1.4em;font-weight:normal;text-align:left;float:left;padding:0;clear:none;} -#plugin__manager .plugins .button{font-size:95%;}#plugin__manager .plugins fieldset.buttons{border:none;} -#plugin__manager .plugins fieldset.buttons .button{float:left;} -#plugin__manager .pm_info h3{margin-left:0;}#plugin__manager .pm_info dl{margin:1em 0;padding:0;} -#plugin__manager .pm_info dt{width:6em;float:left;clear:left;margin:0;padding:0;} -#plugin__manager .pm_info dd{margin:0 0 0 7em;padding:0;background:none;} -#plugin__manager .plugins .enable{float:left;width:auto;margin-right:0.5em;} -#config__manager div.success,#config__manager div.error,#config__manager div.info{background-position:0.5em;padding:0.5em;text-align:center;} -#config__manager fieldset{margin:1em;width:auto;margin-bottom:2em;background-color:#dee7ec;color:#000;padding:0 1em;} -#config__manager legend{font-size:1.25em;} -#config__manager form{}#config__manager table{margin:1em 0;width:100%;}#config__manager fieldset td{text-align:left;} -#config__manager fieldset td.value{width:31em;}#config__manager td.label{padding:0.8em 0 0.6em 1em;vertical-align:top; -}#config__manager td.label label{clear:left;display:block;} -#config__manager td.label img{padding:0 10px;vertical-align:middle;float:right;} -#config__manager td.label span.outkey{font-size:70%;margin-top:-1.7em;margin-left:-1em;display:block;background-color:#fff;color:#666;float:left;padding:0 0.1em;position:relative;z-index:1;} -#config__manager td input.edit{width:30em;}#config__manager td .input{width:30.8em;} -#config__manager td select.edit{}#config__manager td textarea.edit{width:27.5em;height:4em;} -#config__manager tr .input,#config__manager tr input,#config__manager tr textarea,#config__manager tr select{background-color:#fff;color:#000;} -#config__manager tr.default .input,#config__manager tr.default input,#config__manager tr.default textarea,#config__manager tr.default select,#config__manager .selectiondefault{background-color:#cdf;color:#000;} -#config__manager tr.protected .input,#config__manager tr.protected input,#config__manager tr.protected textarea,#config__manager tr.protected select,#config__manager tr.protected .selection{background-color:#fcc!important;color:#000 !important;} -#config__manager td.error{background-color:red;color:#000;}#config__manager .selection{width:14.8em;float:left;margin:0 0.3em 2px 0;}#config__manager .selection label{float:right;width:14em;font-size:90%;} -* html #config__manager .selection label{padding-top:2px;} -#config__manager .selection input.checkbox{padding-left:0.7em;} -#config__manager .other{clear:both;padding-top:0.5em;} -#config__manager .other label{padding-left:2px;font-size:90%;}.dokuwiki div.plugin_translation{float:right;font-size:95%;} -.dokuwiki div.plugin_translation ul{display:inline;padding:0;margin:0;} -.dokuwiki div.plugin_translation ul li{float:left;list-style-type:none;padding:0;margin:0;} -.dokuwiki div.plugin_translation ul li a.wikilink1:link,.dokuwiki div.plugin_translation ul li a.wikilink1:hover,.dokuwiki div.plugin_translation ul li a.wikilink1:active,.dokuwiki div.plugin_translation ul li a.wikilink1:visited{background-color:#000080;color:#fff !important;text-decoration:none;padding:0 0.2em;margin:0.1em 0.2em;border:none !important;} -.dokuwiki div.plugin_translation ul li a.wikilink2:link,.dokuwiki div.plugin_translation ul li a.wikilink2:hover,.dokuwiki div.plugin_translation ul li a.wikilink2:active,.dokuwiki div.plugin_translation ul li a.wikilink2:visited{background-color:#808080;color:#fff !important;text-decoration:none;padding:0 0.2em;margin:0.1em 0.2em;border:none !important;} -.dokuwiki div.plugin_translation ul li a img{opacity:0.5;border:0;} -.dokuwiki div.plugin_translation ul li a.wikilink2 img{}.dokuwiki div.plugin_translation span.curid a img{opacity:1.0;height:15px;} -.dokuwiki div.plugin_translation ul li a:hover img{opacity:1.0;height:15px;}#user__manager tr.disabled{color:#6f6f6f;background:#e4e4e4;} -#user__manager tr.user_info{vertical-align:top;} -#user__manager div.edit_user{width:46%;float:left;}#user__manager table{margin-bottom:1em;}#user__manager input.button[disabled]{color:#ccc!important;border-color:#ccc!important;}div.dokuwiki div.newentry_form{clear:both;text-align:center;margin-bottom:1em;} -div.dokuwiki #blog__newentry_form input.edit{width:95%;}div.dokuwiki tr.draft,div.dokuwiki div.draft{opacity:0.5;} -div.dokuwiki div.autoarchive_selector ul{list-style-type:none;clear:left;margin:0 0.5em 0 0;} -div.dokuwiki div.autoarchive_selector ul div.li{float:left;margin:0 1em 0 0;} -div.dokuwiki div.autoarchive_selector ul ul{float:left;clear:none;}div.dokuwiki div.autoarchive_selector ul ul div.li{margin:0;}div#acl_manager div#acl__tree{font-size:90%;width:25%;height:300px;float:left;overflow:auto;border:1px solid #8cacbb;text-align:left;} -div#acl_manager div#acl__tree a.cur{background-color:#ff9;font-weight:bold;} -div#acl_manager div#acl__tree ul{list-style-type:none;margin:0;padding:0;}div#acl_manager div#acl__tree li{padding-left:1em;}div#acl_manager div#acl__tree ul img{margin-right:0.25em;cursor:pointer;} -div#acl_manager div#acl__detail{width:73%;height:300px;float:right;overflow:auto;} -div#acl_manager div#acl__detail fieldset{width:90%;} -div#acl_manager div#acl__detail div#acl__user{border:1px solid #8cacbb;padding:0.5em;margin-bottom:0.6em;} -div#acl_manager table.inline{width:100%;margin:0;} -div#acl_manager .aclgroup{background:transparent url(static/default/group.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;} -div#acl_manager .acluser{background:transparent url(static/default/user.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;} -div#acl_manager .aclpage{background:transparent url(static/default/page.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;} -div#acl_manager .aclns{background:transparent url(static/default/ns.png) 0px 1px no-repeat;padding:1px 0px 1px 18px;} -div#acl_manager label.disabled{color:#666!important;} -#acl_manager label{text-align:left;font-weight:normal;display:inline;} -#acl_manager table{margin-left:10%;width:80%;}#acl_manager table tr{background-color:inherit;} -#acl_manager table tr:hover{background-color:#dee7ec;} - - -a.interwiki{background:transparent url(/lib/images/interwiki.png) 0px 1px no-repeat;padding-left:16px;} -a.iw_wp{background-image:url(/static/default/wp.gif)} -a.iw_wpde{background-image:url(/static/default/wpde.gif)} -a.iw_wpmeta{background-image:url(/static/default/wpmeta.gif)} -a.iw_doku{background-image:url(/static/default/doku.gif)} -a.iw_dokubug{background-image:url(/static/default/dokubug.gif)} -a.iw_amazon{background-image:url(/static/default/amazon.gif)} -a.iw_amazon_de{background-image:url(/static/default/amazon.de.gif)} -a.iw_amazon_uk{background-image:url(/static/default/amazon.uk.gif)} -a.iw_phpfn{background-image:url(/static/default/phpfn.gif)} -a.iw_coral{background-image:url(/static/default/coral.gif)} -a.iw_sb{background-image:url(/static/default/sb.gif)} -a.iw_google{background-image:url(/static/default/google.gif)} -a.iw_meatball{background-image:url(/static/default/meatball.gif)} -a.iw_wiki{background-image:url(/static/default/wiki.gif)} -a.mediafile{background:transparent url(/static/default/file.png) 0px 1px no-repeat;padding-left:18px;padding-bottom:1px;}a.mf_jpg{background-image:url(/static/default/jpg.png)}a.mf_jpeg{background-image:url(/static/default/jpeg.png)}a.mf_gif{background-image:url(/static/default/gif.png)}a.mf_png{background-image:url(/static/default/png.png)}a.mf_tgz{background-image:url(/static/default/tgz.png)}a.mf_tar{background-image:url(/static/default/tar.png)}a.mf_gz{background-image:url(/static/default/gz.png)}a.mf_bz2{background-image:url(/static/default/bz2.png)} -a.mf_zip{background-image:url(/static/default/zip.png)}a.mf_rar{background-image:url(/static/default/rar.png)}a.mf_pdf{background-image:url(/static/default/pdf.png)}a.mf_ps{background-image:url(/static/default/ps.png)}a.mf_doc{background-image:url(/static/default/doc.png)}a.mf_xls{background-image:url(/static/default/xls.png)}a.mf_ppt{background-image:url(/static/default/ppt.png)}a.mf_rtf{background-image:url(/static/default/rtf.png)}a.mf_swf{background-image:url(/static/default/swf.png)}a.mf_rpm{background-image:url(/static/default/rpm.png)}a.mf_deb{background-image:url(/static/default/deb.png)}a.mf_sxw{background-image:url(/static/default/sxw.png)}a.mf_sxc{background-image:url(/static/default/sxc.png)}a.mf_sxi{background-image:url(/static/default/sxi.png)}a.mf_sxd{background-image:url(/static/default/sxd.png)}a.mf_odc{background-image:url(/static/default/odc.png)}a.mf_odf{background-image:url(/static/default/odf.png)}a.mf_odg{background-image:url(/static/default/odg.png)} -a.mf_odi{background-image:url(/static/default/odi.png)}a.mf_odp{background-image:url(/static/default/odp.png)}a.mf_ods{background-image:url(/static/default/ods.png)}a.mf_odt{background-image:url(/static/default/odt.png)}body{margin:0px;padding:0px;background-color:white;color:black;font-size:12px;font-family:Verdana,Helvetica,"Lucida Grande",Lucida,Arial,sans-serif;font-family:sans-serif;font-size:99,96%;font-size-adjust:none;font-style:normal;font-variant:normal;font-weight:normal;line-height:normal;}hr{border-width:0px;border-bottom:1px #aaa dotted;}img{border:none;}form{margin:0px;padding:0px;border:none;display:inline;background:transparent;}ul li{margin:5px;}textarea{font-family:monospace;}table{margin:0.5em 0;border-collapse:collapse;}td{padding:0.25em;border:1pt solid #ADB9CC;}a{color:#3465a4;text-decoration:none;}a:hover{text-decoration:underline;} -a.wikilink2{color:#a40000 !important;}.dokuwiki h1 a,.dokuwiki h2 a,.dokuwiki h3 a,.dokuwiki h4 a,.dokuwiki h5 a,.dokuwiki a.nolink{color:#000 !important;text-decoration:none !important;} -option{border:0px none #fff;}strong.highlight{background-color:#fc9;padding:1pt;}#pagebottom{clear:both;}hr{height:1px;color:#c0c0c0;background-color:#c0c0c0;border:none;margin:.2em 0 .2em 0;}pre{padding:0.5em;font-family:courier,monospace;border:1px solid #c0c0c0;background:#F0ECE6;white-space:pre;white-space:pre-wrap;word-wrap:break-word;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;}.invisible{margin:0px;border:0px;padding:0px;height:0px;visibility:hidden;}.left{float:left !important;}.right{float:right !important;}.center{text-align:center;}div#body-wrapper{padding:40px 40px 10px 40px;font-size:127%;} -div#content{margin-top:-20px;padding:0;font-size:14px;color:black;line-height:1.5em;}h1,h2,h3,h4,h5,h6{background:transparent none repeat scroll 0 0;border-bottom:1px solid #aaa;color:black;font-weight:normal;margin:0;padding:0;padding-bottom:0.17em;padding-top:0.5em;}h1{font-size:188%;line-height:1.2em;margin-bottom:0.1em;padding-bottom:0;}h2{font-size:150%;}h3,h4,h5,h6{border-bottom:none;font-weight:bold;}h3{font-size:132%;}h4{font-size:116%;}h5{font-size:100%;}h6{font-size:80%;}ul#page-actions{float:right;margin:10px 10px 0 10px;padding:6px;color:black;background-color:#ececec;list-style-type:none;-moz-border-radius:5px;}ul#user-actions{padding:5px;margin:0;display:inline;color:black;background-color:#ececec;list-style-type:none;-moz-border-radius:3px;}ul#page-actions li,ul#user-actions li{display:inline;}ul#page-actions a,ul#user-actions a{text-decoration:none;color:black;display:inline;margin:0 3px;padding:2px 0px 2px 18px;} -ul#page-actions a:hover,ul#page-actions a:focus,ul#user-actions a:hover,ul#user-actions a:focus{text-decoration:underline;}.hidden{display:none;}a.urlextern{color:#36B;background:transparent url(/static/default/external-10.2.png) no-repeat scroll right center;padding:0 13px 0 0;}a[href^="http://www.pyload.org"]:after,a.noextlink:after{background:none;padding:0;}a.action.index{background:transparent url(/static/default/wiki-tools-index.png) 0px 1px no-repeat;}a.action.recent{background:transparent url(/static/default/wiki-tools-recent.png) 0px 1px no-repeat;}a.logout{background:transparent url(/static/default/user-actions-logout.png) 0px 1px no-repeat;} -a.admin{background:transparent url(/static/default/user-actions-admin.png) 0px 1px no-repeat;}a.profile{background:transparent url(/static/default/user-actions-profile.png) 0px 1px no-repeat;}a.create,a.edit{background:transparent url(/static/default/page-tools-edit.png) 0px 1px no-repeat;}a.source,a.show{background:transparent url(/static/default/page-tools-source.png) 0px 1px no-repeat;}a.revisions{background:transparent url(/static/default/page-tools-revisions.png) 0px 1px no-repeat;}a.subscribe,a.unsubscribe{background:transparent url(/static/default/page-tools-subscribe.png) 0px 1px no-repeat;}a.backlink{background:transparent url(/static/default/page-tools-backlinks.png) 0px 1px no-repeat;}#head-panel{background:#525252 url(/static/default/head_bg1.png) bottom left repeat-x;}#head-panel h1{display:none;margin:0;text-decoration:none;padding-top:0.8em;padding-left:3.3em;font-size:2.6em;color:#eeeeec;}#head-panel #head-logo{float:left;margin:5px 0 -15px 5px;padding:0;overflow:visible;}#head-menu{background:transparent url(/static/default/tabs-border-bottom.png) 0 100% repeat-x;width:100%;float:left;margin:0;padding:0;padding-top:0.8em;} -#head-menu ul{list-style:none;margin:0 1em 0 2em;}#head-menu ul li{float:left;margin:0;margin-left:0.3em;font-size:14px;margin-bottom:4px;}#head-menu ul li.selected,#head-menu ul li:hover{margin-bottom:0px;}#head-menu ul li a img{height:22px;width:22px;vertical-align:middle;}#head-menu ul li a,#head-menu ul li a:link{float:left;text-decoration:none;color:#555;background:#eaeaea url(/static/default/tab-background.png) 0 100% repeat-x;padding:3px 7px 3px 7px;border:2px solid #ccc;border-bottom:0px solid transparent;padding-bottom:3px;-moz-border-radius:5px;}#head-menu ul li a:hover,#head-menu ul li a:focus{color:#111;padding-bottom:7px;border-bottom:0px none transparent;outline:none;-moz-border-radius-bottomright:0px;-moz-border-radius-bottomleft:0px;}#head-menu ul li a:focus{margin-bottom:-4px;}#head-menu ul li.selected a{color:#3566A5;background:#fff;padding-bottom:7px;border-bottom:0px none transparent;-moz-border-radius-bottomright:0px;-moz-border-radius-bottomleft:0px;}#head-menu ul li.selected a:hover,#head-menu ul li.selected a:focus{color:#111;}div#head-search-and-login{float:right;margin:0 1em 0 0;background-color:#222;padding:4px;color:white;-moz-border-radius-bottomright:6px;-moz-border-radius-bottomleft:6px;}div#head-search-and-login form{display:inline;padding:0 3px;}div#head-search-and-login form input{border:2px solid #888;background:#eee;font-size:14px;padding:2px;-moz-border-radius:3px;}div#head-search-and-login form input:focus{background:#fff;}#head-search{font-size:14px;}#head-username,#head-password{width:80px;font-size:14px;}#pageinfo{clear:both;color:#888;padding:0.6em 0;margin:0;}#foot{font-style:normal;color:#888;text-align:center;}#foot a{color:#aaf;}#foot img{vertical-align:middle;}ul.toc{padding:0;padding-left:20px;margin-left:0;margin-right:10px;list-style:none;}ul.toc li{list-style:circle;}ul.toc li a{text-decoration:none;color:black;}ul.toc li a:hover{text-decoration:underline;}div.toc{border:1px dotted #888;background:#f0f0f0;margin:1em 0 1em 1em;float:right;font-size:95%;}div.toc .tocheader{font-weight:bold;margin:0.5em 1em;}div.toc ol{margin:1em 0.5em 1em 1em;padding:0;}div.toc ol li{margin:0;padding:0;margin-left:1em;}div.toc ol ol{margin:0.5em 0.5em 0.5em 1em;padding:0;}div.recentchanges table{clear:both;}div#editor-help{font-size:90%;border:1px dotted #888;padding:0ex 1ex 1ex 1ex;background:#f7f6f2;}div#preview{margin-top:1em;}label.block{display:block;text-align:right;font-weight:bold;}label.simple{display:block;text-align:left;font-weight:normal;}label.block input.edit{width:50%;}fieldset{width:300px;text-align:center;padding:0.5em;margin:auto;}div.editor{margin:0 0 0 0;}table{margin:0.5em 0;border-collapse:collapse;}td{padding:0.25em;border:1pt solid #ADB9CC;}td p{margin:0;padding:0;}.u{text-decoration:underline;}.footnotes ul{padding:0 2em;margin:0 0 1em;}.footnotes li{list-style:none;}.recentchanges p{margin:0.25em;}.recentchanges td{vertical-align:top;border:none;border-bottom:1pt solid #F0ECE6;background:#F7F6F2;}.rcdaybreak td{background:#729fcf;border:none;}.rcdaybreak td a{font-size:0.88em;}.rcicon1,.rcicon2{text-align:center;}.rcpagelink{width:33%;}.rctime{font-size:0.88em;white-space:nowrap;}.rceditor{white-space:nowrap;font-size:0.88em;}.rccomment{width:66%;color:gray;font-size:0.88em;}.rcrss{float:right;}.recentchanges[dir="rtl"] .rcrss{float:left;}.userpref table,.userpref td{border:none;}div.codearea{margin:0.5em 0;padding:0;border:1pt solid #AEBDCC;background-color:#F3F5F7;color:black;}div.codearea pre{margin:0;padding:10pt;border:none;}a.codenumbers{margin:0 10pt;font-size:0.85em;color:gray;}div.codearea pre span.LineNumber{color:gray;}div.codearea pre span.ID{color:#000;}div.codearea pre span.Operator{color:#0000c0;}div.codearea pre span.Char{color:#004080;}div.codearea pre span.Comment{color:#008000;}div.codearea pre span.Number{color:#0080c0;}div.codearea pre span.String{color:#004080;}div.codearea pre span.SPChar{color:#0000c0;}div.codearea pre span.ResWord{color:#a00000;}div.codearea pre span.ConsWord{color:#008080;font-weight:bold;}div.codearea pre span.Error{color:#ff8080;border:solid 1.5pt #f00;}div.codearea pre span.ResWord2{color:#0080ff;font-weight:bold;}div.codearea pre span.Special{color:#00f;}div.codearea pre span.Preprc{color:#803999;}#message{clear:both;padding:5px 10px;background-color:#eee;border-bottom:2px solid #ccc;}#message p{margin:5px 0;padding:0;font-weight:bold;}#message div.buttons{font-weight:normal;}.diff{width:99%;}.diff-title{background-color:#C0C0C0;}.searchresult dd span{font-weight:bold;}.diff{width:100%;border:none;}.diff-blockheader{font-weight:bold;background:#e5e5e5;font-size:1.2em;border-top:2px solid #444;padding:5px;}.diff th{font-size:120%;width:50%;font-weight:normal;text-align:left;padding-bottom:3px;}.diff td{font-family:monospace;font-size:100%;border:none;}.diff-addedline{background-color:#dfd;}.diff-deletedline{background-color:#ffb;}.diff-context{color:#888;}.diff-addedline{background-color:#E0FFE0;vertical-align:sub;}.diff-deletedline{background-color:#FFFFE0;background-color:#f4cece;vertical-align:sub;} -.diff-addedline strong{background-color:#80FF80;background-color:#8ae234;} -.diff-deletedline strong{background-color:#FFFF80;background-color:#ef2929;background-color:#d78383;} - - - -.box{ background:url(/static/default/progress-bar-back.gif) right center no-repeat; width:200px; height:20px; float:left; } -.perc{ background:url(/static/default/progress-bar.gif) right center no-repeat; height:20px; } -.boxtext{ font-family:tahoma, arial, sans-serif; font-size:11px; color:#000; float:none; padding:3px 0 0 10px; } -.statusbutton{width:32px;height:32px;float:left;margin-left:-32px;margin-right:5px;opacity:0;cursor:pointer} - -.dlsize{float:left; padding-right: 8px;} -.dlspeed{float:left; padding-right: 8px;}
\ No newline at end of file diff --git a/module/web/static/favicon.ico b/module/web/static/favicon.icoBinary files differ deleted file mode 100644 index 58b1f4b89..000000000 --- a/module/web/static/favicon.ico +++ /dev/null diff --git a/module/web/templates/default.tpl b/module/web/templates/default.tpl deleted file mode 100644 index 3f5e8d8e8..000000000 --- a/module/web/templates/default.tpl +++ /dev/null @@ -1,230 +0,0 @@ -%header =  'pyLoad Webinterface' -%js = ['mootools-1.2.3-core.js','mootools-1.2.3.1-more.js'] - -%if page== "home": js.append('default/home.js') -%end -%if page== "loggedin": red=True -%else: red=False -%end -%if page != "loggedin" and page != "login": js.append('default/status.js') -%end - -%include header title=header, use_js=js, use_css=['default.css','window.css'], redirect=red - -%include window id="addlinks", width=400, caption="Add links", body="<input id='pname' type='text' style='width: 345px;' value='Package'/><textarea rows=10 style='width: 345px;' id='linkarea'></textarea>", button="Add" - -<a class="anchor" name="top" id="top"></a> - -<div id="head-panel"> - - -	<div id="head-search-and-login"> - -%if page != "login": -				<img src="static/default/head-login.png" alt="User:" style="vertical-align:middle; margin:2px" /><span style="padding-right: 2px;">{{user}}</span> -					<ul id="user-actions"> -				<li><a href="/logout"  class="action logout" rel="nofollow">Logout</a></li> -				<li></li> -				<li></li> -			</ul> -%else: -    <span style="padding-right: 2px;">Please Login!</span> -	 - -%end -	</div> - -	<a href="/"><img id="head-logo" src="/static/default/pyload-logo-edited3.5-new-font-small.png" alt="pyLoad" /></a> - -	<div id="head-menu"> -		<ul> -	<li class=" -        %if page == "home" or page == "login": -        selected -        %endif -        "><a href="/" title=""><img src="static/default/head-menu-home.png" alt="" /> Home</a></li> -        <li class="  -        %if page == "queue": -        selected -        %endif -        "><a href="/queue" title=""><img src="static/default/head-menu-download.png" alt="" /> Queue</a></li> -        <li class=" -        %if page == "downloads": -        selected -        %endif -        "><a href="/downloads" title=""><img src="static/default/head-menu-development.png" alt="" /> Downloads</a></li> -        <li class="right"><a href="/logs"  class="action index" accesskey="x" rel="nofollow"><img src="static/default/head-menu-index.png" alt="" />Logs</a></li>		</ul> -	</div> - -	<div style="clear:both;"></div> -</div> - -<ul id="page-actions"> -	<li><a href=""  class="action revisions" accesskey="o" rel="nofollow">Reload page</a></li> - -</ul> - -<div id="body-wrapper" class="dokuwiki"> - -	<div id="content" lang="en" dir="ltr"> - - -<h1><a name="pyload_download_manager_for_1_click_hoster" id="pyload_download_manager_for_1_click_hoster">pyLoad — Webinterface</a> -</h1> - - -%if page != "loggedin" and page != "login": - -<div id="statusbar"> -  <div id="status" style="float: left;padding: 8px;"> -Status: -</div> -  <div id="speed" style="float: left;padding: 8px"> -Speed:  -</div> - - <div id="queue" style="float: left;padding: 8px"> -Files in queue:  -</div> - -<div style="padding-top:2px"> - -<div style="background-image:url(static/default/Button-Play.png);width:32px;height:32px;float:left"></div> -<div class= "statusbutton" style="background-image:url(static/default/Button-Play-grey.png); visibility: visible; opacity: 0.01"></div> -<div style="background-image:url(static/default/Button-Pause.png);width:32px;height:32px;float:left"></div> -<div class= "statusbutton" style="background-image:url(static/default/Button-Pause-grey.png); visibility: visible; opacity: 0.01"></div> -<div style="background-image:url(static/default/Button-Add.png);width:32px;height:32px;float:left"></div> -<div class= "statusbutton" style="background-image:url(static/default/Button-Add-grey.png); visibility: visible; opacity: 0.01"></div> - - -</div> - -</div> - -%end - - -<br> - -<div class="level1" style="clear:both"> - -%if page == "login": - -</div> -<div class="centeralign"> -<form action="" method="post" accept-charset="utf-8" id="login"><div class="no"> -<input type="hidden" name="do" value="login" /><fieldset ><legend>Login</legend> -<label class="block" for="focus__this"><span>Username</span> <input type="text" id="focus__this" name="u" class="edit" /></label><br /> -<label class="block"><span>Password</span> <input type="password" name="p" class="edit" /></label><br /> -<input type="submit" value="Login" class="button" /> -</fieldset> -</div></form> -</div> -<br> - -%elif page== "home": -<h2>Downloads:</h2> - -<div id="dlcontainer"> - -% for link in links: - - -<div class="download" id="dl{{link['id']}}" style="color: #000"> -<p></p> - -<b>{{link['name']}}</b> -<br> -<script type="text/javascript"> -pbs[{{link['id']}}] = new dwProgressBar({ -        container: document.id('dl{{link['id']}}'), -        startPercentage: {{link['percent']}}, -        speed: 1000, -        id: {{link['id']}}, -        boxID: 'box', -        percentageID: 'perc', -        displayText: true, -        displayID: 'boxtext' -}); - -dls.push({{link['id']}}) - -</script> - - -<div class="dlsize"> -{{int((link['size'] - link['kbleft']) / 1024)}}/{{int(link['size']) / 1024}} MB -</div> - - -<div class="dlspeed"> -{{int(link['speed'])}} kb/s -</div> - - -<div class="dltime"> -{{link['eta']}} -</div> - - -</div> - - -<script type="text/javascript"> -$$("#dl{{link['id']}}")[0].hover(function(e){ - -this.morph({'color': '#f00'}); - -}, function(e){ - -this.morph({'color': '#000'}); - -}); - - -</script> - - -%end - -</div> - - -%elif page=="loggedin": - - -<b>You were successfully logged in</b> - -%elif page=="queue": - -<ul> - -%for package in links: - -<li>{{package.name}}</li> - -%end - -</ul> - -Currently in Development - -%elif page=="downloads": - -Currently in Development - - -%end -	<hr style="clear: both;" /> - -<div id="foot">© 2008-2009 the pyLoad Team - -	<a href="#top" class="action top" accesskey="x"><span>Back to top</span></a><br /> -	<!--<div class="breadcrumbs"></div>--> - - -</div> - -</div> - -%include footer use_js=[]
\ No newline at end of file diff --git a/module/web/templates/default/base.html b/module/web/templates/default/base.html new file mode 100644 index 000000000..096692a3c --- /dev/null +++ b/module/web/templates/default/base.html @@ -0,0 +1,99 @@ +<?xml version="1.0" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/default.css"> +{% block head %} +{% endblock %} +<title>{% block title %}pyLoad Webinterface{% endblock %}</title> +</head> + +<a class="anchor" name="top" id="top"></a> + +<div id="head-panel"> + +<div id="head-search-and-login"> + +{% if user.is_authenticated %} +<img src="{{ MEDIA_URL }}img/head-login.png" alt="User:" style="vertical-align:middle; margin:2px" /><span style="padding-right: 2px;">{{user.username}}</span> +	<ul id="user-actions"> +		<li><a href="/logout"  class="action logout" rel="nofollow">Logout</a></li> +		{% if user.is_staff %} +		<li><a href="/admin" class="action profile" rel="nofollow">Administrate</a></li> +		{% endif %} +		<li></li> +		<li></li> +	</ul> +{% else %} +    <span style="padding-right: 2px;">Please Login!</span> +{% endif %} + +	</div> + +	<a href="/"><img id="head-logo" src="{{ MEDIA_URL }}img/pyload-logo-edited3.5-new-font-small.png" alt="pyLoad" /></a> + +	<div id="head-menu"> +		<ul> +			 +		{% block menu %} +		<li class="selected"> +		    <a href="/" title=""><img src="{{ MEDIA_URL }}img/head-menu-home.png" alt="" /> Home</a> +		</li> +		<li> +		    <a href="/queue/" title=""><img src="{{ MEDIA_URL }}img/head-menu-download.png" alt="" /> Queue</a></li> +		<li> +		    <a href="/downloads/" title=""><img src="{{ MEDIA_URL }}img/head-menu-development.png" alt="" /> Downloads</a></li> +		<li class="right"> +		    <a href="/logs/"  class="action index" accesskey="x" rel="nofollow"><img src="{{ MEDIA_URL }}img/head-menu-index.png" alt="" />Logs</a> +		</li> +		{% endblock %} +		 +		</ul> +	</div> + +	<div style="clear:both;"></div> +</div> + +<ul id="page-actions"> +	<li><a href=""  class="action revisions" accesskey="o" rel="nofollow">Reload page</a></li> + +</ul> + +<div id="body-wrapper" class="dokuwiki"> + +<div id="content" lang="en" dir="ltr"> + +<h1><a name="pyload_download_manager_for_1_click_hoster" id="pyload_download_manager_for_1_click_hoster">pyLoad — Webinterface</a> +</h1> + +{% block statusbar %} +{% endblock %} + + +<br> + +<div class="level1" style="clear:both"> +</div> + +{% for message in messages %} +	<b><p>{{message}}</p></b> +{% endfor %} + +{% block content %} +{% endblock content %} + +	<hr style="clear: both;" /> + +<div id="foot">© 2008-2010 the pyLoad Team + +	<a href="#top" class="action top" accesskey="x"><span>Back to top</span></a><br /> +	<!--<div class="breadcrumbs"></div>--> + + +</div> +</div> +</head> +<body> diff --git a/module/web/templates/default/downloads.html b/module/web/templates/default/downloads.html new file mode 100644 index 000000000..3c9bb5df4 --- /dev/null +++ b/module/web/templates/default/downloads.html @@ -0,0 +1,16 @@ +{% extends 'default/base.html' %} + +{% block title %}Downloads - {{block.super}} {% endblock %} + +{% block menu %} +<li> +    <a href="/" title=""><img src="{{ MEDIA_URL }}img/head-menu-home.png" alt="" /> Home</a> +</li> +<li> +    <a href="/queue" title=""><img src="{{ MEDIA_URL }}img/head-menu-download.png" alt="" /> Queue</a></li> +<li class="selected"> +    <a href="/downloads" title=""><img src="{{ MEDIA_URL }}img/head-menu-development.png" alt="" /> Downloads</a></li> +<li class="right"> +    <a href="/logs"  class="action index" accesskey="x" rel="nofollow"><img src="{{ MEDIA_URL }}img/head-menu-index.png" alt="" />Logs</a> +</li> +{% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/home.html b/module/web/templates/default/home.html new file mode 100644 index 000000000..895302e61 --- /dev/null +++ b/module/web/templates/default/home.html @@ -0,0 +1 @@ +{% extends 'default/base.html' %}
\ No newline at end of file diff --git a/module/web/templates/default/login.html b/module/web/templates/default/login.html new file mode 100644 index 000000000..851802c4f --- /dev/null +++ b/module/web/templates/default/login.html @@ -0,0 +1,35 @@ +{% extends 'default/base.html' %} + +{% block title %}Login - {{block.super}} {% endblock %} + +{% block content %} + +<div class="centeralign"> +<form action="" method="post" accept-charset="utf-8" id="login"> +    <div class="no"> +        <input type="hidden" name="do" value="login" /> +        <fieldset> +        <legend>Login</legend> +        <label class="block" for="focus__this"> +            <span>Username</span> +            {{ form.username }} +        </label> +        <br /> +        <label class="block"> +            <span>Password</span> +            {{ form.password }} +        </label> +        <br /> +        <input type="submit" value="Login" class="button" /> +        </fieldset> +    </div> +</form> + +{% if form.errors %} +<p>Your username and password didn't match. Please try again.</p> +{% endif %} + +</div> +<br> +     +{% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/logout.html b/module/web/templates/default/logout.html new file mode 100644 index 000000000..4d00bf6d5 --- /dev/null +++ b/module/web/templates/default/logout.html @@ -0,0 +1,9 @@ +{% extends 'default/base.html' %} + +{% block head %} +<meta http-equiv="refresh" content="3; url=/"> +{% endblock %} + +{% block content %} +<p><b>You were successfully logged out.</b></p>     +{% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/logs.html b/module/web/templates/default/logs.html new file mode 100644 index 000000000..d6f392f58 --- /dev/null +++ b/module/web/templates/default/logs.html @@ -0,0 +1,16 @@ +{% extends 'default/base.html' %} + +{% block title %}Logs - {{block.super}} {% endblock %} + +{% block menu %} +<li> +    <a href="/" title=""><img src="{{ MEDIA_URL }}img/head-menu-home.png" alt="" /> Home</a> +</li> +<li> +    <a href="/queue" title=""><img src="{{ MEDIA_URL }}img/head-menu-download.png" alt="" /> Queue</a></li> +<li> +    <a href="/downloads" title=""><img src="{{ MEDIA_URL }}img/head-menu-development.png" alt="" /> Downloads</a></li> +<li class="right" class="selected"> +    <a href="/logs"  class="action index" accesskey="x" rel="nofollow"><img src="{{ MEDIA_URL }}img/head-menu-index.png" alt="" />Logs</a> +</li> +{% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/queue.html b/module/web/templates/default/queue.html new file mode 100644 index 000000000..b6a185b19 --- /dev/null +++ b/module/web/templates/default/queue.html @@ -0,0 +1,16 @@ +{% extends 'default/base.html' %} + +{% block title %}Queue - {{block.super}} {% endblock %} + +{% block menu %} +<li> +    <a href="/" title=""><img src="{{ MEDIA_URL }}img/head-menu-home.png" alt="" /> Home</a> +</li> +<li class="selected"> +    <a href="/queue" title=""><img src="{{ MEDIA_URL }}img/head-menu-download.png" alt="" /> Queue</a></li> +<li> +    <a href="/downloads" title=""><img src="{{ MEDIA_URL }}img/head-menu-development.png" alt="" /> Downloads</a></li> +<li class="right"> +    <a href="/logs"  class="action index" accesskey="x" rel="nofollow"><img src="{{ MEDIA_URL }}img/head-menu-index.png" alt="" />Logs</a> +</li> +{% endblock %}
\ No newline at end of file diff --git a/module/web/templates/window.tpl b/module/web/templates/default/window.html index f756c4352..f756c4352 100644 --- a/module/web/templates/window.tpl +++ b/module/web/templates/default/window.html diff --git a/module/web/templates/footer.tpl b/module/web/templates/footer.tpl deleted file mode 100644 index a59b414bf..000000000 --- a/module/web/templates/footer.tpl +++ /dev/null @@ -1,6 +0,0 @@ -%for item in use_js: -<script type="text/javascript" src="static/{{item}}"></script> -%end - -</body> -</html> diff --git a/module/web/templates/header.tpl b/module/web/templates/header.tpl deleted file mode 100644 index 22c252e3c..000000000 --- a/module/web/templates/header.tpl +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" -    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> - -%for item in use_js: -<script type="text/javascript" src="static/{{item}}"></script> -%end - -%for item in use_css: -<link rel="stylesheet" type="text/css" href="static/{{item}}"> -%end - -<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> - -%if redirect: -<meta http-equiv="refresh" content="3; url=/"> -%end - -<title>{{title}}</title> - -</head> -<body> diff --git a/module/web/urls.py b/module/web/urls.py new file mode 100644 index 000000000..3e573aa95 --- /dev/null +++ b/module/web/urls.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from django.conf.urls.defaults import * +from django.contrib import admin +from django.conf import settings + +from os.path import join + +admin.autodiscover() + +urlpatterns = patterns('', +                       # Example: +                       # (r'^pyload/', include('pyload.foo.urls')), + +                       # Uncomment the admin/doc line below and add 'django.contrib.admindocs' +                       # to INSTALLED_APPS to enable admin documentation: +                       # (r'^admin/doc/', include('django.contrib.admindocs.urls')), + +                       # Uncomment the next line to enable the admin: +                        (r'^admin/', include(admin.site.urls)), +                       #(r'^json/', include(ajax.urls)), +                        (r'^media/(?P<path>.*)$', 'django.views.static.serve', +                         {'document_root': settings.MEDIA_ROOT}), +                       (r'^login/$', 'django.contrib.auth.views.login', {'template_name': join(settings.TEMPLATE,'login.html')}), +                       (r'^logout/$', 'django.contrib.auth.views.logout', {'template_name': join(settings.TEMPLATE,'logout.html')}), +                       (r'^home/$', 'pyload.views.home'), +                       (r'^downloads/$', 'pyload.views.downloads'), +                       (r'^queue/$', 'pyload.views.queue'), +                       (r'^logs/$', 'pyload.views.logs'), +                       (r'^$', 'pyload.views.home'), +                       ) | 
