Beispiel #1
0
def load(routes="routes.py", app=None):
    """
    load: read and parse routes.py
    (called from main.py at web2py initialization time)
    store results in params 
    """
    symbols = {}

    if app is None:
        path = abspath(routes)
    else:
        path = abspath("applications", app, routes)
    if not os.path.exists(path):
        return
    try:
        routesfp = open(path, "r")
        exec routesfp.read().replace("\r\n", "\n") in symbols
        routesfp.close()
        logger.debug("URL rewrite is on. configuration in %s" % path)
    except SyntaxError, e:
        routesfp.close()
        logger.error(
            "Your %s has a syntax error " % path + "Please fix it before you restart web2py\n" + traceback.format_exc()
        )
        raise e
Beispiel #2
0
def create_missing_folders():
    if not global_settings.web2py_runtime_gae:
        for path in ("applications", "deposit", "site-packages", "logs"):
            path = abspath(path, gluon=True)
            if not os.path.exists(path):
                os.mkdir(path)
    paths = (global_settings.gluon_parent, abspath("site-packages", gluon=True), abspath("gluon", gluon=True), "")
    [add_path_first(path) for path in paths]
Beispiel #3
0
def create_missing_folders():
    if not global_settings.web2py_runtime_gae:
        for path in ('applications', 'deposit', 'site-packages', 'logs'):
            path = abspath(path, gluon=True)
            if not os.path.exists(path):
                os.mkdir(path)
    paths = (global_settings.gluon_parent, abspath('site-packages', gluon=True),  abspath('gluon', gluon=True), '')
    [add_path_first(path) for path in paths]
Beispiel #4
0
def create_missing_folders():
    if not global_settings.web2py_runtime_gae:
        for path in ('applications', 'deposit', 'site-packages', 'logs'):
            path = abspath(path, gluon=True)
            if not os.path.exists(path):
                os.mkdir(path)
    paths = (global_settings.gluon_parent, abspath('site-packages', gluon=True),  abspath('gluon', gluon=True), '')
    [add_path_first(path) for path in paths]
Beispiel #5
0
 def make_apptree():
     "build a temporary applications tree"
     #  applications/
     os.mkdir(abspath('applications'))
     #  applications/app/
     for app in ('admin', 'examples', 'welcome'):
         os.mkdir(abspath('applications', app))
         #  applications/app/(controllers, static)
         for subdir in ('controllers', 'static'):
             os.mkdir(abspath('applications', app, subdir))
     #  applications/admin/controllers/*.py
     for ctr in ('appadmin', 'default', 'gae', 'mercurial', 'shell', 'wizard'):
         open(abspath('applications', 'admin', 'controllers', '%s.py' % ctr), 'w').close()
     #  applications/examples/controllers/*.py
     for ctr in ('ajax_examples', 'appadmin', 'default', 'global', 'spreadsheet'):
         open(abspath('applications', 'examples', 'controllers', '%s.py' % ctr), 'w').close()
     #  applications/welcome/controllers/*.py
     for ctr in ('appadmin', 'default'):
         open(abspath('applications', 'welcome', 'controllers', '%s.py' % ctr), 'w').close()
     #  create an app-specific routes.py for examples app
     routes = open(abspath('applications', 'examples', 'routes.py'), 'w')
     routes.write("routers=dict(examples=dict(default_function='exdef'))")
     routes.close()
     #  create language files for examples app
     for lang in ('en', 'it'):
         os.mkdir(abspath('applications', 'examples', 'static', lang))
         open(abspath('applications', 'examples', 'static', lang, 'file'), 'w').close()
Beispiel #6
0
def save_password(password, port):
    """
    used by main() to save the password in the parameters_port.py file.
    """

    password_file = abspath('parameters_%i.py' % port)
    if password == '<random>':
        # make up a new password
        chars = string.letters + string.digits
        password = ''.join([random.choice(chars) for i in range(8)])
        cpassword = CRYPT()(password)[0]
        print '******************* IMPORTANT!!! ************************'
        print 'your admin password is "%s"' % password
        print '*********************************************************'
    elif password == '<recycle>':
        # reuse the current password if any
        if exists(password_file):
            return
        else:
            password = ''
    elif password.startswith('<pam_user:'******'w')
    if password:
        fp.write('password="******"\n' % cpassword)
    else:
        fp.write('password=None\n')
    fp.close()
Beispiel #7
0
def read_possible_plurals():
    """ create list of all possible plural rules files
        result is cached to increase speed
    """
    global pcache
    pdir = abspath('gluon', 'contrib', 'rules')
    plurals = {}
    # scan rules directory for plural_rules-*.py files:
    for pname in [
            f for f in listdir(pdir, regex_plural_rules) if osep not in f
    ]:

        lang = pname[13:-3]
        fname = ospath.join(pdir, pname)
        mtime = ostat(fname).st_mtime
        if lang in pcache and pcache[lang][2] == mtime:
            # if plural_file's mtime wasn't changed - use previous value:
            plurals[lang] = pcache[lang]
        else:
            # otherwise, reread plural_rules-file:
            if 'plural_rules-' + lang in cfs:
                n, f1, f2, status = read_plural_rules(lang)
            else:
                n, f1, f2, status = read_plural_rules_aux(fname)
            plurals[lang] = (n, pname, mtime, status)
    pcache = plurals
    return pcache
Beispiel #8
0
def read_possible_plurals():
    """ create list of all possible plural rules files
        result is cached to increase speed
    """
    global pcache
    pdir = abspath('gluon','contrib','rules')
    plurals = {}
    # scan rules directory for plural_rules-*.py files:
    for pname in [f for f in listdir(pdir, regex_plural_rules)
                  if osep not in f]:

        lang=pname[13:-3]
        fname=ospath.join(pdir, pname)
        mtime=ostat(fname).st_mtime
        if lang in pcache and pcache[lang][2] == mtime:
            # if plural_file's mtime wasn't changed - use previous value:
            plurals[lang]=pcache[lang]
        else:
            # otherwise, reread plural_rules-file:
            if 'plural_rules-'+lang in cfs:
               n,f1,f2,status=read_plural_rules(lang)
            else:
               n,f1,f2,status=read_plural_rules_aux(fname)
            plurals[lang]=(n, pname, mtime, status)
    pcache=plurals
    return pcache
Beispiel #9
0
def save_password(password, port):
    """
    used by main() to save the password in the parameters_port.py file.
    """

    password_file = abspath('parameters_%i.py' % port)
    if password == '<random>':
        # make up a new password
        chars = string.letters + string.digits
        password = ''.join([random.choice(chars) for i in range(8)])
        cpassword = CRYPT()(password)[0]
        print '******************* IMPORTANT!!! ************************'
        print 'your admin password is "%s"' % password
        print '*********************************************************'
    elif password == '<recycle>':
        # reuse the current password if any
        if os.path.exists(password_file):
            return
        else:
            password = ''
    elif password.startswith('<pam_user:'******'w')
    if password:
        fp.write('password="******"\n' % cpassword)
    else:
        fp.write('password=None\n')
    fp.close()
Beispiel #10
0
def load(routes='routes.py', app=None, data=None, rdict=None):
    """
    load: read (if file) and parse routes
    store results in params
    (called from main.py at web2py initialization time)
    If data is present, it's used instead of the routes.py contents.
    If rdict is present, it must be a dict to be used for routers (unit test)
    """
    global params
    global routers
    if app is None:
        # reinitialize
        global params_apps
        params_apps = dict()
        params = _params_default(app=None)  # regex rewrite parameters
        thread.routes = params              # default to base regex rewrite parameters
        routers = None

    if isinstance(rdict, dict):
        symbols = dict(routers=rdict)
        path = 'rdict'
    else:
        if data is not None:
            path = 'routes'
        else:
            if app is None:
                path = abspath(routes)
            else:
                path = abspath('applications', app, routes)
            if not os.path.exists(path):
                return
            routesfp = open(path, 'r')
            data = routesfp.read().replace('\r\n','\n')
            routesfp.close()

        symbols = {}
        try:
            exec (data + '\n') in symbols
        except SyntaxError, e:
            logger.error(
                '%s has a syntax error and will not be loaded\n' % path
                + traceback.format_exc())
            raise e
Beispiel #11
0
def load(routes='routes.py', app=None, data=None, rdict=None):
    """
    load: read (if file) and parse routes
    store results in params
    (called from main.py at web2py initialization time)
    If data is present, it's used instead of the routes.py contents.
    If rdict is present, it must be a dict to be used for routers (unit test)
    """
    global params
    global routers
    if app is None:
        # reinitialize
        global params_apps
        params_apps = dict()
        params = _params_default(app=None)  # regex rewrite parameters
        thread.routes = params  # default to base regex rewrite parameters
        routers = None

    if isinstance(rdict, dict):
        symbols = dict(routers=rdict)
        path = 'rdict'
    else:
        if data is not None:
            path = 'routes'
        else:
            if app is None:
                path = abspath(routes)
            else:
                path = abspath('applications', app, routes)
            if not os.path.exists(path):
                return
            routesfp = open(path, 'r')
            data = routesfp.read().replace('\r\n', '\n')
            routesfp.close()

        symbols = {}
        try:
            exec(data + '\n') in symbols
        except SyntaxError, e:
            logger.error('%s has a syntax error and will not be loaded\n' %
                         path + traceback.format_exc())
            raise e
Beispiel #12
0
    def start(self):
        import newcron
        import logging
        import logging.config
        from settings import global_settings
        from fileutils import abspath
        from os.path import exists, join
        
        self.log('web2py Cron service starting')
        if not self.chdir():
            return
        if len(sys.argv) == 2:
            opt_mod = sys.argv[1]
        else:
            opt_mod = self._exe_args_
        options = __import__(opt_mod, [], [], '')
        logpath = abspath(join(options.folder, "logging.conf"))
        
        if exists(logpath):
            logging.config.fileConfig(logpath)
        else:
            logging.basicConfig()
        logger = logging.getLogger("web2py.cron")
        global_settings.web2py_crontype = 'external'
        if options.scheduler:   # -K
            apps = [app.strip() for app in options.scheduler.split(
                    ',') if check_existent_app(options, app.strip())]
        else:
            apps = None

        misfire_gracetime = float(options.misfire_gracetime) if 'misfire_gracetime' in dir(options) else 0.0
        logger.info('Starting Window cron service with %0.2f secs gracetime.' % misfire_gracetime)
        self._started = True
        wait_full_min = lambda: 60 - time.time() % 60
        while True:
            try:
                if wait_full_min() >= misfire_gracetime: # an offset of max. 5 secs before full minute (e.g. time.sleep(60) == 58.99 secs)
                    self.extcron = newcron.extcron(options.folder, apps=apps)
                    self.extcron.start()
                    time.sleep(wait_full_min())
                else:
                    logger.debug('time.sleep() offset detected: %0.3f s' % wait_full_min())
                    while wait_full_min() <= misfire_gracetime:
                        pass
                if apps != None:
                    break
                if not self._started:
                    break
            except Exception, ex:
                self.extcron = None
                self.log_error('%s, restarting service.' % ex)
                logger.exception('Exception! Restarting Windows cron service.' % ex)
                self.start()
Beispiel #13
0
def load(routes='routes.py', app=None):
    """
    load: read and parse routes.py
    (called from main.py at web2py initialization time)
    store results in params
    """
    if app is None:
        path = abspath(routes)
    else:
        path = abspath('applications', app, routes)
    if not os.path.exists(path):
        return

    symbols = {}
    try:
        routesfp = open(path, 'r')
        exec routesfp.read().replace('\r\n', '\n') in symbols
        routesfp.close()
    except SyntaxError, e:
        routesfp.close()
        logger.error('%s has a syntax error and will not be loaded\n' % path +
                     traceback.format_exc())
        raise e
Beispiel #14
0
def load(routes='routes.py', app=None):
    """
    load: read and parse routes.py
    (called from main.py at web2py initialization time)
    store results in params
    """
    if app is None:
        path = abspath(routes)
    else:
        path = abspath('applications', app, routes)
    if not os.path.exists(path):
        return

    symbols = {}
    try:
        routesfp = open(path, 'r')
        exec routesfp.read().replace('\r\n','\n') in symbols
        routesfp.close()
    except SyntaxError, e:
        routesfp.close()
        logger.error(
            '%s has a syntax error and will not be loaded\n' % path
            + traceback.format_exc())
        raise e
Beispiel #15
0
def upgrade(request, url='http://web2py.com'):
    """
    Upgrades web2py (src, osx, win) is a new version is posted.
    It detects whether src, osx or win is running and downloads the right one

    Parameters
    ----------
    request:
        the current request object, required to determine version and path
    url:
        the incomplete url where to locate the latest web2py
        actual url is url+'/examples/static/web2py_(src|osx|win).zip'

    Returns
    -------
        True on success, False on failure (network problem or old version)
    """
    web2py_version = request.env.web2py_version
    gluon_parent = request.env.gluon_parent
    if not gluon_parent.endswith('/'):
        gluon_parent = gluon_parent + '/'
    (check, version) = check_new_version(web2py_version,
                                         url+'/examples/default/version')
    if not check:
        return (False, 'Already latest version')
    if os.path.exists(os.path.join(gluon_parent, 'web2py.exe')):
        version_type = 'win'
        destination = gluon_parent
        subfolder = 'web2py/'
    elif gluon_parent.endswith('/Contents/Resources/'):
        version_type = 'osx'
        destination = gluon_parent[:-len('/Contents/Resources/')]
        subfolder = 'web2py/web2py.app/'
    else:
        version_type = 'src'
        destination = gluon_parent
        subfolder = 'web2py/'

    full_url = url + '/examples/static/web2py_%s.zip' % version_type
    filename = abspath('web2py_%s_downloaded.zip' % version_type)
    file = None
    try:
        file = open(filename,'wb')
        file.write(urllib.urlopen(full_url).read())
        file.close()
    except Exception,e:
        file and file.close()
        return False, e
Beispiel #16
0
def upgrade(request, url="http://web2py.com"):
    """
    Upgrades web2py (src, osx, win) is a new version is posted.
    It detects whether src, osx or win is running and downloads the right one

    Parameters
    ----------
    request:
        the current request object, required to determine version and path
    url:
        the incomplete url where to locate the latest web2py
        actual url is url+'/examples/static/web2py_(src|osx|win).zip'

    Returns
    -------
        True on success, False on failure (network problem or old version)
    """
    web2py_version = request.env.web2py_version
    gluon_parent = request.env.gluon_parent
    if not gluon_parent.endswith("/"):
        gluon_parent = gluon_parent + "/"
    (check, version) = check_new_version(web2py_version, url + "/examples/default/version")
    if not check:
        return (False, "Already latest version")
    if os.path.exists(os.path.join(gluon_parent, "web2py.exe")):
        version_type = "win"
        destination = gluon_parent
        subfolder = "web2py/"
    elif gluon_parent.endswith("/Contents/Resources/"):
        version_type = "osx"
        destination = gluon_parent[: -len("/Contents/Resources/")]
        subfolder = "web2py/web2py.app/"
    else:
        version_type = "src"
        destination = gluon_parent
        subfolder = "web2py/"

    full_url = url + "/examples/static/web2py_%s.zip" % version_type
    filename = abspath("web2py_%s_downloaded.zip" % version_type)
    file = None
    try:
        write_file(filename, urllib.urlopen(full_url).read(), "wb")
    except Exception, e:
        return False, e
Beispiel #17
0
def read_possible_plurals():
    """
    create list of all possible plural rules files
    result is cached to increase speed
    """
    pdir = abspath('gluon','contrib','rules')
    plurals = {}
    # scan rules directory for plural_rules-*.py files:
    for pname in os.listdir(pdir):
        if not isdir(pname) and regex_plural_rules.match(pname):
            lang = pname[13:-3]
            fname = ospath.join(pdir, pname)
            n, f1, f2, status = read_global_plural_rules(fname)
            if status == 'ok':
                plurals[lang] = (lang, n, f1, f2, pname)
    plurals['default'] = ('default',
                          DEFAULT_NPLURALS,
                          DEFAULT_GET_PLURAL_ID,
                          DEFAULT_CONSTRUCTOR_PLURAL_FORM,
                          None)
    return plurals
Beispiel #18
0
def unzip(filename, dir, subfolder=''):
    """
    Unzips filename into dir (.zip only, no .gz etc)
    if subfolder!='' it unzip only files in subfolder
    """
    filename = abspath(filename)
    if not zipfile.is_zipfile(filename):
        raise RuntimeError('Not a valid zipfile')
    zf = zipfile.ZipFile(filename)
    if not subfolder.endswith('/'):
        subfolder = subfolder + '/'
    n = len(subfolder)
    for name in sorted(zf.namelist()):
        if not name.startswith(subfolder):
            continue
        #print name[n:]
        if name.endswith('/'):
            folder = os.path.join(dir, name[n:])
            if not os.path.exists(folder):
                os.mkdir(folder)
        else:
            write_file(os.path.join(dir, name[n:]), zf.read(name), 'wb')
Beispiel #19
0
def unzip(filename, dir, subfolder=''):
    """
    Unzips filename into dir (.zip only, no .gz etc)
    if subfolder!='' it unzip only files in subfolder
    """
    filename = abspath(filename)
    if not zipfile.is_zipfile(filename):
        raise RuntimeError, 'Not a valid zipfile'
    zf = zipfile.ZipFile(filename)
    if not subfolder.endswith('/'):
        subfolder = subfolder + '/'
    n = len(subfolder)
    for name in sorted(zf.namelist()):
        if not name.startswith(subfolder):
            continue
        #print name[n:]
        if name.endswith('/'):
            folder = os.path.join(dir,name[n:])
            if not os.path.exists(folder):
                os.mkdir(folder)
        else:
            write_file(os.path.join(dir, name[n:]), zf.read(name), 'wb')
Beispiel #20
0
 def make_apptree():
     "build a temporary applications tree"
     #  applications/
     os.mkdir(abspath("applications"))
     #  applications/app/
     for app in ("admin", "examples", "welcome"):
         os.mkdir(abspath("applications", app))
         #  applications/app/(controllers, static)
         for subdir in ("controllers", "static"):
             os.mkdir(abspath("applications", app, subdir))
     #  applications/admin/controllers/*.py
     for ctr in ("appadmin", "default", "gae", "mercurial", "shell", "wizard"):
         open(abspath("applications", "admin", "controllers", "%s.py" % ctr), "w").close()
     #  applications/examples/controllers/*.py
     for ctr in ("ajax_examples", "appadmin", "default", "global", "spreadsheet"):
         open(abspath("applications", "examples", "controllers", "%s.py" % ctr), "w").close()
     #  applications/welcome/controllers/*.py
     for ctr in ("appadmin", "default"):
         open(abspath("applications", "welcome", "controllers", "%s.py" % ctr), "w").close()
     #  create an app-specific routes.py for examples app
     routes = open(abspath("applications", "examples", "routes.py"), "w")
     routes.write("default_function='exdef'\n")
     routes.close()
Beispiel #21
0
    def __init__(
        self,
        ip='127.0.0.1',
        port=8000,
        password='',
        pid_filename='httpserver.pid',
        log_filename='httpserver.log',
        profiler_filename=None,
        ssl_certificate=None,
        ssl_private_key=None,
        ssl_ca_certificate=None,
        min_threads=None,
        max_threads=None,
        server_name=None,
        request_queue_size=5,
        timeout=10,
        socket_timeout = 1,
        shutdown_timeout=None, # Rocket does not use a shutdown timeout
        path=None,
        interfaces=None # Rocket is able to use several interfaces - must be list of socket-tuples as string
        ):
        """
        starts the web server.
        """

        if interfaces:
            # if interfaces is specified, it must be tested for rocket parameter correctness
            # not necessarily completely tested (e.g. content of tuples or ip-format)
            import types
            if isinstance(interfaces,types.ListType):
                for i in interfaces:
                    if not isinstance(i,types.TupleType):
                        raise "Wrong format for rocket interfaces parameter - see http://packages.python.org/rocket/"
            else:
                raise "Wrong format for rocket interfaces parameter - see http://packages.python.org/rocket/"

        if path:
            # if a path is specified change the global variables so that web2py
            # runs from there instead of cwd or os.environ['web2py_path']
            global web2py_path
            path = os.path.normpath(path)
            web2py_path = path
            global_settings.applications_parent = path
            os.chdir(path)
            [add_path_first(p) for p in (path, abspath('site-packages'), "")]
            custom_import_install(web2py_path)
            if os.path.exists("logging.conf"):
                logging.config.fileConfig("logging.conf")

        save_password(password, port)
        self.pid_filename = pid_filename
        if not server_name:
            server_name = socket.gethostname()
        logger.info('starting web server...')
        rocket.SERVER_NAME = server_name
        rocket.SOCKET_TIMEOUT = socket_timeout
        sock_list = [ip, port]
        if not ssl_certificate or not ssl_private_key:
            logger.info('SSL is off')
        elif not rocket.ssl:
            logger.warning('Python "ssl" module unavailable. SSL is OFF')
        elif not os.path.exists(ssl_certificate):
            logger.warning('unable to open SSL certificate. SSL is OFF')
        elif not os.path.exists(ssl_private_key):
            logger.warning('unable to open SSL private key. SSL is OFF')
        else:
            sock_list.extend([ssl_private_key, ssl_certificate])
            if ssl_ca_certificate:
                sock_list.append(ssl_ca_certificate)

            logger.info('SSL is ON')
        app_info = {'wsgi_app': appfactory(wsgibase,
                                           log_filename,
                                           profiler_filename) }

        self.server = rocket.Rocket(interfaces or tuple(sock_list),
                                    method='wsgi',
                                    app_info=app_info,
                                    min_threads=min_threads,
                                    max_threads=max_threads,
                                    queue_size=int(request_queue_size),
                                    timeout=int(timeout),
                                    handle_signals=False,
                                    )
Beispiel #22
0
        #
        routers = params.routers    # establish routers if present
        if isinstance(routers, dict):
            routers = Storage(routers)
        if routers is not None:
            router = _router_default()
            if routers.BASE:
                router.update(routers.BASE)
            routers.BASE = router

        #  scan each app in applications/
        #    create a router, if routers are in use
        #    parse the app-specific routes.py if present
        #
        all_apps = []
        for appname in [app for app in os.listdir(abspath('applications')) if not app.startswith('.')]:
            if os.path.isdir(abspath('applications', appname)) and \
               os.path.isdir(abspath('applications', appname, 'controllers')):
                all_apps.append(appname)
                if routers:
                    router = Storage(routers.BASE)   # new copy
                    if appname in routers:
                        for key in routers[appname].keys():
                            if key in ROUTER_BASE_KEYS:
                                raise SyntaxError, "BASE-only key '%s' in router '%s'" % (key, appname)
                        router.update(routers[appname])
                    routers[appname] = router
                if os.path.exists(abspath('applications', appname, routes)):
                    load(routes, appname)

        if routers:
Beispiel #23
0
def crondance(applications_parent, ctype='soft', startup=False):
    apppath = os.path.join(applications_parent, 'applications')
    cron_path = os.path.join(apppath, 'admin', 'cron')
    token = Token(cron_path)
    cronmaster = token.acquire(startup=startup)
    if not cronmaster:
        return
    now_s = time.localtime()
    checks = (('min', now_s.tm_min), ('hr', now_s.tm_hour), ('mon',
                                                             now_s.tm_mon),
              ('dom', now_s.tm_mday), ('dow', (now_s.tm_wday + 1) % 7))

    apps = [
        x for x in os.listdir(apppath)
        if os.path.isdir(os.path.join(apppath, x))
    ]

    for app in apps:
        if _cron_stopping:
            break
        apath = os.path.join(apppath, app)
        cronpath = os.path.join(apath, 'cron')
        crontab = os.path.join(cronpath, 'crontab')
        if not os.path.exists(crontab):
            continue
        try:
            cronlines = fileutils.readlines_file(crontab, 'rt')
            lines = [
                x.strip() for x in cronlines
                if x.strip() and not x.strip().startswith('#')
            ]
            tasks = [parsecronline(cline) for cline in lines]
        except Exception, e:
            logger.error('WEB2PY CRON: crontab read error %s' % e)
            continue

        for task in tasks:
            if _cron_stopping:
                break
            commands = [sys.executable]
            w2p_path = fileutils.abspath('web2py.py', gluon=True)
            if os.path.exists(w2p_path):
                commands.append(w2p_path)
            if global_settings.applications_parent != global_settings.gluon_parent:
                commands.extend(('-f', global_settings.applications_parent))
            citems = [(k in task and not v in task[k]) for k, v in checks]
            task_min = task.get('min', [])
            if not task:
                continue
            elif not startup and task_min == [-1]:
                continue
            elif task_min != [-1] and reduce(lambda a, b: a or b, citems):
                continue
            logger.info('WEB2PY CRON (%s): %s executing %s in %s at %s' \
                             % (ctype, app, task.get('cmd'),
                                os.getcwd(), datetime.datetime.now()))
            action, command, models = False, task['cmd'], ''
            if command.startswith('**'):
                (action, models, command) = (True, '', command[2:])
            elif command.startswith('*'):
                (action, models, command) = (True, '-M', command[1:])
            else:
                action = False
            if action and command.endswith('.py'):
                commands.extend((
                    '-J',  # cron job
                    models,  # import models?
                    '-S',
                    app,  # app name
                    '-a',
                    '"<recycle>"',  # password
                    '-R',
                    command))  # command
                shell = True
            elif action:
                commands.extend((
                    '-J',  # cron job
                    models,  # import models?
                    '-S',
                    app + '/' + command,  # app name
                    '-a',
                    '"<recycle>"'))  # password
                shell = True
            else:
                commands = command
                shell = False
            try:
                cronlauncher(commands, shell=shell).start()
            except Exception, e:
                logger.warning(
                    'WEB2PY CRON: Execution error for %s: %s' \
                        % (task.get('cmd'), e))
Beispiel #24
0
def read_plural_rules(lang):
    filename = abspath('gluon','contrib','rules', 'plural_rules-%s.py' % lang)
    return getcfs('plural_rules-'+lang, filename,
               lambda: read_plural_rules_aux(filename))
Beispiel #25
0
    for sym in ('routes_app', 'routes_in', 'routes_out'):
        if sym in symbols:
            for (k, v) in symbols[sym]:
                p[sym].append(compile_re(k, v))
    for sym in ('routes_onerror', 'routes_apps_raw',
                'error_handler','error_message', 'error_message_ticket',
                'default_application','default_controller', 'default_function'):
        if sym in symbols:
            p[sym] = symbols[sym]

    if app is None:
        global params
        params = p  # install base rewrite parameters
        for appname in os.listdir('applications'):
            if os.path.exists(abspath('applications', appname, routes)):
                load(routes, appname)
    else:
        params_apps[app] = p
    logger.debug('URL rewrite is on. configuration in %s' % path)

def filter_uri(e, regexes, tag, default=None):
    "filter incoming URI against a list of regexes"
    query = e.get('QUERY_STRING', None)
    path = e['PATH_INFO']
    host = e.get('HTTP_HOST', 'localhost').lower()
    original_uri = path + (query and '?'+query or '')
    i = host.find(':')
    if i > 0:
        host = host[:i]
    key = '%s:%s://%s:%s %s' % \
Beispiel #26
0
def wsgibase(environ, responder):
    """
    this is the gluon wsgi application. the first function called when a page
    is requested (static or dynamic). it can be called by paste.httpserver
    or by apache mod_wsgi.

      - fills request with info
      - the environment variables, replacing '.' with '_'
      - adds web2py path and version info
      - compensates for fcgi missing path_info and query_string
      - validates the path in url

    The url path must be either:

    1. for static pages:

      - /<application>/static/<file>

    2. for dynamic pages:

      - /<application>[/<controller>[/<function>[/<sub>]]][.<extension>]
      - (sub may go several levels deep, currently 3 levels are supported:
         sub1/sub2/sub3)

    The naming conventions are:

      - application, controller, function and extension may only contain
        [a-zA-Z0-9_]
      - file and sub may also contain '-', '=', '.' and '/'
    """

    current.__dict__.clear()
    request = Request()
    response = Response()
    session = Session()
    request.env.web2py_path = global_settings.applications_parent
    request.env.web2py_version = web2py_version
    request.env.update(global_settings)
    static_file = False
    try:
        try:
            try:
                # ##################################################
                # handle fcgi missing path_info and query_string
                # select rewrite parameters
                # rewrite incoming URL
                # parse rewritten header variables
                # parse rewritten URL
                # serve file if static
                # ##################################################

                if not environ.get('PATH_INFO',None) and \
                        environ.get('REQUEST_URI',None):
                    # for fcgi, get path_info and query_string from request_uri
                    items = environ['REQUEST_URI'].split('?')
                    environ['PATH_INFO'] = items[0]
                    if len(items) > 1:
                        environ['QUERY_STRING'] = items[1]
                    else:
                        environ['QUERY_STRING'] = ''
                if not environ.get('HTTP_HOST',None):
                    environ['HTTP_HOST'] = '%s:%s' % (environ.get('SERVER_NAME'),
                                                      environ.get('SERVER_PORT'))

                (static_file, environ) = rewrite.url_in(request, environ)
                if static_file:
                    if request.env.get('query_string', '')[:10] == 'attachment':
                        response.headers['Content-Disposition'] = 'attachment'
                    response.stream(static_file, request=request)

                # ##################################################
                # fill in request items
                # ##################################################

                http_host = request.env.http_host.split(':',1)[0]

                local_hosts = [http_host,'::1','127.0.0.1','::ffff:127.0.0.1']
                if not global_settings.web2py_runtime_gae:
                    local_hosts += [socket.gethostname(),
                                    socket.gethostbyname(http_host)]
                request.client = get_client(request.env)
                request.folder = abspath('applications',
                                         request.application) + os.sep
                x_req_with = str(request.env.http_x_requested_with).lower()
                request.ajax = x_req_with == 'xmlhttprequest'
                request.cid = request.env.http_web2py_component_element
                request.is_local = request.env.remote_addr in local_hosts
                request.is_https = request.env.wsgi_url_scheme \
                    in ['https', 'HTTPS'] or request.env.https == 'on'

                # ##################################################
                # compute a request.uuid to be used for tickets and toolbar
                # ##################################################

                response.uuid = request.compute_uuid()

                # ##################################################
                # access the requested application
                # ##################################################

                if not os.path.exists(request.folder):
                    if request.application == \
                            rewrite.thread.routes.default_application \
                            and request.application != 'welcome':
                        request.application = 'welcome'
                        redirect(Url(r=request))
                    elif rewrite.thread.routes.error_handler:
                        _handler = rewrite.thread.routes.error_handler
                        redirect(Url(_handler['application'],
                                     _handler['controller'],
                                     _handler['function'],
                                     args=request.application))
                    else:
                        raise HTTP(404, rewrite.thread.routes.error_message \
                                       % 'invalid request',
                                   web2py_error='invalid application')
                elif not request.is_local and \
                        os.path.exists(os.path.join(request.folder,'DISABLED')):
                    raise HTTP(200, "<html><body><h1>Down for maintenance</h1></body></html>")
                request.url = Url(r=request, args=request.args,
                                       extension=request.raw_extension)

                # ##################################################
                # build missing folders
                # ##################################################

                create_missing_app_folders(request)

                # ##################################################
                # get the GET and POST data
                # ##################################################

                parse_get_post_vars(request, environ)

                # ##################################################
                # expose wsgi hooks for convenience
                # ##################################################

                request.wsgi.environ = environ_aux(environ,request)
                request.wsgi.start_response = \
                    lambda status='200', headers=[], \
                    exec_info=None, response=response: \
                    start_response_aux(status, headers, exec_info, response)
                request.wsgi.middleware = \
                    lambda *a: middleware_aux(request,response,*a)

                # ##################################################
                # load cookies
                # ##################################################

                if request.env.http_cookie:
                    try:
                        request.cookies.load(request.env.http_cookie)
                    except Cookie.CookieError, e:
                        pass # invalid cookies

                # ##################################################
                # try load session or create new session file
                # ##################################################

                session.connect(request, response)

                # ##################################################
                # set no-cache headers
                # ##################################################

                response.headers['Content-Type'] = \
                    contenttype('.'+request.extension)
                response.headers['Cache-Control'] = \
                    'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
                response.headers['Expires'] = \
                    time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime())
                response.headers['Pragma'] = 'no-cache'

                # ##################################################
                # run controller
                # ##################################################

                serve_controller(request, response, session)

            except HTTP, http_response:
                if static_file:
                    return http_response.to(responder)

                if request.body:
                    request.body.close()

                # ##################################################
                # on success, try store session in database
                # ##################################################
                session._try_store_in_db(request, response)

                # ##################################################
                # on success, commit database
                # ##################################################

                if response.do_not_commit is True:
                    BaseAdapter.close_all_instances(None)
                elif response._custom_commit:
                    response._custom_commit()
                else:
                    BaseAdapter.close_all_instances('commit')

                # ##################################################
                # if session not in db try store session on filesystem
                # this must be done after trying to commit database!
                # ##################################################

                session._try_store_on_disk(request, response)

                # ##################################################
                # store cookies in headers
                # ##################################################

                if request.cid:

                    if response.flash and not 'web2py-component-flash' in http_response.headers:
                        http_response.headers['web2py-component-flash'] = \
                            str(response.flash).replace('\n','')
                    if response.js and not 'web2py-component-command' in http_response.headers:
                        http_response.headers['web2py-component-command'] = \
                            response.js.replace('\n','')
                if session._forget and \
                        response.session_id_name in response.cookies:
                    del response.cookies[response.session_id_name]
                elif session._secure:
                    response.cookies[response.session_id_name]['secure'] = True
                if len(response.cookies)>0:
                    http_response.headers['Set-Cookie'] = \
                        [str(cookie)[11:] for cookie in response.cookies.values()]
                ticket=None

            except RestrictedError, e:

                if request.body:
                    request.body.close()

                # ##################################################
                # on application error, rollback database
                # ##################################################

                ticket = e.log(request) or 'unknown'
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')

                http_response = \
                    HTTP(500, rewrite.thread.routes.error_message_ticket % \
                             dict(ticket=ticket),
                         web2py_error='ticket %s' % ticket)
Beispiel #27
0
if global_settings.db_sessions is not True:
    global_settings.db_sessions = set()
global_settings.gluon_parent = os.environ.get('web2py_path', os.getcwd())
global_settings.applications_parent = global_settings.gluon_parent
web2py_path = global_settings.applications_parent # backward compatibility
global_settings.app_folders = set()
global_settings.debugging = False

custom_import_install(web2py_path)

create_missing_folders()

# set up logging for subsequent imports
import logging
import logging.config
logpath = abspath("logging.conf")
if os.path.exists(logpath):
    logging.config.fileConfig(abspath("logging.conf"))
else:
    logging.basicConfig()
logger = logging.getLogger("web2py")

from restricted import RestrictedError
from http import HTTP, redirect
from globals import Request, Response, Session
from compileapp import build_environment, run_models_in, \
    run_controller_in, run_view_in
from fileutils import copystream
from contenttype import contenttype
from dal import BaseAdapter
from settings import global_settings
Beispiel #28
0
    def start(self):
        import newcron
        import logging
        import logging.config
        from settings import global_settings
        from fileutils import abspath
        from os.path import exists, join

        self.log('web2py Cron service starting')
        if not self.chdir():
            return
        if len(sys.argv) == 2:
            opt_mod = sys.argv[1]
        else:
            opt_mod = self._exe_args_
        options = __import__(opt_mod, [], [], '')
        logpath = abspath(join(options.folder, "logging.conf"))

        if exists(logpath):
            logging.config.fileConfig(logpath)
        else:
            logging.basicConfig()
        logger = logging.getLogger("web2py.cron")
        global_settings.web2py_crontype = 'external'
        if options.scheduler:  # -K
            apps = [
                app.strip() for app in options.scheduler.split(',')
                if check_existent_app(options, app.strip())
            ]
        else:
            apps = None

        misfire_gracetime = float(
            options.misfire_gracetime) if 'misfire_gracetime' in dir(
                options) else 0.0
        logger.info('Starting Window cron service with %0.2f secs gracetime.' %
                    misfire_gracetime)
        self._started = True
        wait_full_min = lambda: 60 - time.time() % 60
        while True:
            try:
                if wait_full_min(
                ) >= misfire_gracetime:  # an offset of max. 5 secs before full minute (e.g. time.sleep(60) == 58.99 secs)
                    self.extcron = newcron.extcron(options.folder, apps=apps)
                    self.extcron.start()
                    time.sleep(wait_full_min())
                else:
                    logger.debug('time.sleep() offset detected: %0.3f s' %
                                 wait_full_min())
                    while wait_full_min() <= misfire_gracetime:
                        pass
                if apps != None:
                    break
                if not self._started:
                    break
            except Exception, ex:
                self.extcron = None
                self.log_error('%s, restarting service.' % ex)
                logger.exception(
                    'Exception! Restarting Windows cron service.' % ex)
                self.start()
Beispiel #29
0
#  set sys.path to ("", gluon_parent/site-packages, gluon_parent, ...)
# 
#  this is wrong:
#  web2py_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
#  because we do not want the path to this file which may be Library.zip
#
#  gluon_parent is the directory containing gluon, web2py.py, logging.conf and the handlers.
#  applications_parent (web2py_path) is the directory containing applications/ and routes.py
#  The two are identical unless web2py_path is changed via the web2py.py -f folder option
#  main.web2py_path is the same as applications_parent (for backward compatibility)
#
global_settings.gluon_parent = os.environ.get('web2py_path', os.getcwd())
global_settings.applications_parent = global_settings.gluon_parent
web2py_path = global_settings.applications_parent # backward compatibility

for path in (global_settings.gluon_parent, abspath('site-packages', gluon=True), ""):
    try:
        sys.path.remove(path)
    except ValueError:
        pass
    sys.path.insert(0, path)

# set up logging for subsequent imports
import logging
import logging.config
logpath = abspath("logging.conf")
if os.path.exists(logpath):
    logging.config.fileConfig(abspath("logging.conf"))
else:
    logging.basicConfig()
logger = logging.getLogger("web2py")
Beispiel #30
0
def appfactory(wsgiapp=wsgibase,
               logfilename='httpserver.log',
               profiler_dir=None):
    """
    generates a wsgi application that does logging and profiling and calls
    wsgibase

    .. function:: gluon.main.appfactory(
            [wsgiapp=wsgibase
            [, logfilename='httpserver.log'
            [, profilerfilename='profiler.log']]])

    """

    if profiler_dir:
        profiler_dir = abspath(profiler_dir)
        logger.warn('profiler is on. will use dir %s', profiler_dir)
        if not os.path.isdir(profiler_dir):
            try:
                os.makedirs(profiler_dir)
            except:
                raise BaseException, "Can't create dir %s" % profiler_dir
        filepath = pjoin(profiler_dir, 'wtest')
        try:
            filehandle = open( filepath, 'w' )
            filehandle.close()
            os.unlink(filepath)
        except IOError:
            raise BaseException, "Unable to write to dir %s" % profiler_dir

    def app_with_logging(environ, responder):
        """
        a wsgi app that does logging and profiling and calls wsgibase
        """
        status_headers = []

        def responder2(s, h):
            """
            wsgi responder app
            """
            status_headers.append(s)
            status_headers.append(h)
            return responder(s, h)

        time_in = time.time()
        ret = [0]
        if not profiler_dir:
            ret[0] = wsgiapp(environ, responder2)
        else:
            import cProfile
            prof = cProfile.Profile()
            prof.enable()
            ret[0] = wsgiapp(environ, responder2)
            prof.disable()
            destfile = pjoin(profiler_dir, "req_%s.prof" % web2py_uuid())
            prof.dump_stats(destfile)

        try:
            line = '%s, %s, %s, %s, %s, %s, %f\n' % (
                environ['REMOTE_ADDR'],
                datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S'),
                environ['REQUEST_METHOD'],
                environ['PATH_INFO'].replace(',', '%2C'),
                environ['SERVER_PROTOCOL'],
                (status_headers[0])[:3],
                time.time() - time_in,
            )
            if not logfilename:
                sys.stdout.write(line)
            elif isinstance(logfilename, str):
                write_file(logfilename, line, 'a')
            else:
                logfilename.write(line)
        except:
            pass
        return ret[0]

    return app_with_logging
Beispiel #31
0
    def __init__(
        self,
        ip='127.0.0.1',
        port=8000,
        password='',
        pid_filename='httpserver.pid',
        log_filename='httpserver.log',
        profiler_filename=None,
        ssl_certificate=None,
        ssl_private_key=None,
        ssl_ca_certificate=None,
        min_threads=None,
        max_threads=None,
        server_name=None,
        request_queue_size=5,
        timeout=10,
        socket_timeout=1,
        shutdown_timeout=None,  # Rocket does not use a shutdown timeout
        path=None,
        interfaces=None  # Rocket is able to use several interfaces - must be list of socket-tuples as string
    ):
        """
        starts the web server.
        """

        if interfaces:
            # if interfaces is specified, it must be tested for rocket parameter correctness
            # not necessarily completely tested (e.g. content of tuples or ip-format)
            import types
            if isinstance(interfaces, types.ListType):
                for i in interfaces:
                    if not isinstance(i, types.TupleType):
                        raise "Wrong format for rocket interfaces parameter - see http://packages.python.org/rocket/"
            else:
                raise "Wrong format for rocket interfaces parameter - see http://packages.python.org/rocket/"

        if path:
            # if a path is specified change the global variables so that web2py
            # runs from there instead of cwd or os.environ['web2py_path']
            global web2py_path
            path = os.path.normpath(path)
            web2py_path = path
            global_settings.applications_parent = path
            os.chdir(path)
            [add_path_first(p) for p in (path, abspath('site-packages'), "")]
            if exists("logging.conf"):
                logging.config.fileConfig("logging.conf")

        save_password(password, port)
        self.pid_filename = pid_filename
        if not server_name:
            server_name = socket.gethostname()
        logger.info('starting web server...')
        rocket.SERVER_NAME = server_name
        rocket.SOCKET_TIMEOUT = socket_timeout
        sock_list = [ip, port]
        if not ssl_certificate or not ssl_private_key:
            logger.info('SSL is off')
        elif not rocket.ssl:
            logger.warning('Python "ssl" module unavailable. SSL is OFF')
        elif not exists(ssl_certificate):
            logger.warning('unable to open SSL certificate. SSL is OFF')
        elif not exists(ssl_private_key):
            logger.warning('unable to open SSL private key. SSL is OFF')
        else:
            sock_list.extend([ssl_private_key, ssl_certificate])
            if ssl_ca_certificate:
                sock_list.append(ssl_ca_certificate)

            logger.info('SSL is ON')
        app_info = {
            'wsgi_app': appfactory(wsgibase, log_filename, profiler_filename)
        }

        self.server = rocket.Rocket(
            interfaces or tuple(sock_list),
            method='wsgi',
            app_info=app_info,
            min_threads=min_threads,
            max_threads=max_threads,
            queue_size=int(request_queue_size),
            timeout=int(timeout),
            handle_signals=False,
        )
Beispiel #32
0
        #
        routers = params.routers    # establish routers if present
        if isinstance(routers, dict):
            routers = Storage(routers)
        if routers is not None:
            router = _router_default()
            if routers.BASE:
                router.update(routers.BASE)
            routers.BASE = router

        #  scan each app in applications/
        #    create a router, if routers are in use
        #    parse the app-specific routes.py if present
        #
        all_apps = []
        for appname in os.listdir(abspath('applications')):
            if os.path.isdir(abspath('applications', appname)):
                all_apps.append(appname)
                if routers:
                    router = Storage(routers.BASE)   # new copy
                    if appname in routers:
                        for key in routers[appname].keys():
                            if key in ROUTER_BASE_KEYS:
                                raise SyntaxError, "BASE-only key '%s' in router '%s'" % (key, appname)
                        router.update(routers[appname])
                    routers[appname] = router
                if os.path.exists(abspath('applications', appname, routes)):
                    load(routes, appname)

        if routers:
            load_routers(all_apps)
Beispiel #33
0
def crondance(applications_parent, ctype="soft", startup=False, apps=None):
    apppath = os.path.join(applications_parent, "applications")
    cron_path = os.path.join(applications_parent)
    token = Token(cron_path)
    cronmaster = token.acquire(startup=startup)
    if not cronmaster:
        return
    now_s = time.localtime()
    checks = (
        ("min", now_s.tm_min),
        ("hr", now_s.tm_hour),
        ("mon", now_s.tm_mon),
        ("dom", now_s.tm_mday),
        ("dow", (now_s.tm_wday + 1) % 7),
    )

    if apps is None:
        apps = [x for x in os.listdir(apppath) if os.path.isdir(os.path.join(apppath, x))]

    full_apath_links = set()

    for app in apps:
        if _cron_stopping:
            break
        apath = os.path.join(apppath, app)

        # if app is a symbolic link to other app, skip it
        full_apath_link = absolute_path_link(apath)
        if full_apath_link in full_apath_links:
            continue
        else:
            full_apath_links.add(full_apath_link)

        cronpath = os.path.join(apath, "cron")
        crontab = os.path.join(cronpath, "crontab")
        if not os.path.exists(crontab):
            continue
        try:
            cronlines = fileutils.readlines_file(crontab, "rt")
            lines = [x.strip() for x in cronlines if x.strip() and not x.strip().startswith("#")]
            tasks = [parsecronline(cline) for cline in lines]
        except Exception, e:
            logger.error("WEB2PY CRON: crontab read error %s" % e)
            continue

        for task in tasks:
            if _cron_stopping:
                break
            if sys.executable.lower().endswith("pythonservice.exe"):
                _python_exe = os.path.join(sys.exec_prefix, "python.exe")
            else:
                _python_exe = sys.executable
            commands = [_python_exe]
            w2p_path = fileutils.abspath("web2py.py", gluon=True)
            if os.path.exists(w2p_path):
                commands.append(w2p_path)
            if applications_parent != global_settings.gluon_parent:
                commands.extend(("-f", applications_parent))
            citems = [(k in task and not v in task[k]) for k, v in checks]
            task_min = task.get("min", [])
            if not task:
                continue
            elif not startup and task_min == [-1]:
                continue
            elif task_min != [-1] and reduce(lambda a, b: a or b, citems):
                continue
            logger.info(
                "WEB2PY CRON (%s): %s executing %s in %s at %s"
                % (ctype, app, task.get("cmd"), os.getcwd(), datetime.datetime.now())
            )
            action, command, models = False, task["cmd"], ""
            if command.startswith("**"):
                (action, models, command) = (True, "", command[2:])
            elif command.startswith("*"):
                (action, models, command) = (True, "-M", command[1:])
            else:
                action = False

            if action and command.endswith(".py"):
                commands.extend(
                    (
                        "-J",  # cron job
                        models,  # import models?
                        "-S",
                        app,  # app name
                        "-a",
                        '"<recycle>"',  # password
                        "-R",
                        command,
                    )
                )  # command
            elif action:
                commands.extend(
                    (
                        "-J",  # cron job
                        models,  # import models?
                        "-S",
                        app + "/" + command,  # app name
                        "-a",
                        '"<recycle>"',
                    )
                )  # password
            else:
                commands = command

            # from python docs:
            # You do not need shell=True to run a batch file or
            # console-based executable.
            shell = False

            try:
                cronlauncher(commands, shell=shell).start()
            except Exception, e:
                logger.warning("WEB2PY CRON: Execution error for %s: %s" % (task.get("cmd"), e))
Beispiel #34
0
#
# See <web2py-root-dir>/router.example.py for parameter's detail
#-------------------------------------------------------------------------------------
# To enable this route file you must do the steps:
#
# 1. rename <web2py-root-dir>/router.example.py to routes.py
# 2. rename this APP/routes.example.py to APP/routes.py
#    (where APP - is your application directory)
# 3. restart web2py (or reload routes in web2py admin interfase)
#
# YOU CAN COPY THIS FILE TO ANY APPLICATION'S ROOT DIRECTORY WITHOUT CHANGES!

from fileutils import abspath
from languages import read_possible_languages

possible_languages = read_possible_languages(abspath('applications', app))
#NOTE! app - is an application based router's parameter with name of an
#            application. E.g.'welcome'

routers = {
    app:
    dict(default_language=possible_languages['default'][0],
         languages=[lang for lang in possible_languages if lang != 'default'])
}

routers = dict(BASE=dict(default_application='py2manager'), )

routes_onerror = [('*/*', '/py2manager/static/error.html')]
#NOTE! To change language in your application using these rules add this line
#in one of your models files:
#   if request.uri_language: T.force(request.uri_language)
Beispiel #35
0
def read_plural_rules(lang):
    filename = abspath('gluon', 'contrib', 'rules',
                       'plural_rules-%s.py' % lang)
    return getcfs('plural_rules-' + lang, filename,
                  lambda: read_plural_rules_aux(filename))
Beispiel #36
0
def wsgibase(environ, responder):
    """
    this is the gluon wsgi application. the first function called when a page
    is requested (static or dynamic). it can be called by paste.httpserver
    or by apache mod_wsgi.

      - fills request with info
      - the environment variables, replacing '.' with '_'
      - adds web2py path and version info
      - compensates for fcgi missing path_info and query_string
      - validates the path in url

    The url path must be either:

    1. for static pages:

      - /<application>/static/<file>

    2. for dynamic pages:

      - /<application>[/<controller>[/<function>[/<sub>]]][.<extension>]
      - (sub may go several levels deep, currently 3 levels are supported:
         sub1/sub2/sub3)

    The naming conventions are:

      - application, controller, function and extension may only contain
        [a-zA-Z0-9_]
      - file and sub may also contain '-', '=', '.' and '/'
    """

    current.__dict__.clear()
    request = Request()
    response = Response()
    session = Session()
    env = request.env
    env.web2py_path = global_settings.applications_parent
    env.web2py_version = web2py_version
    env.update(global_settings)
    static_file = False
    try:
        try:
            try:
                # ##################################################
                # handle fcgi missing path_info and query_string
                # select rewrite parameters
                # rewrite incoming URL
                # parse rewritten header variables
                # parse rewritten URL
                # serve file if static
                # ##################################################

                fixup_missing_path_info(environ)
                (static_file, version, environ) = url_in(request, environ)
                response.status = env.web2py_status_code or response.status

                if static_file:
                    if environ.get('QUERY_STRING', '').startswith(
                            'attachment'):
                        response.headers['Content-Disposition'] \
                            = 'attachment'
                    if version:
                        response.headers['Cache-Control'] = 'max-age=315360000'
                        response.headers[
                            'Expires'] = 'Thu, 31 Dec 2037 23:59:59 GMT'
                    response.stream(static_file, request=request)

                # ##################################################
                # fill in request items
                # ##################################################
                app = request.application  # must go after url_in!

                if not global_settings.local_hosts:
                    local_hosts = set(['127.0.0.1', '::ffff:127.0.0.1', '::1'])
                    if not global_settings.web2py_runtime_gae:
                        try:
                            fqdn = socket.getfqdn()
                            local_hosts.add(socket.gethostname())
                            local_hosts.add(fqdn)
                            local_hosts.update([
                                ip[4][0] for ip in socket.getaddrinfo(
                                    fqdn, 0)])
                            if env.server_name:
                                local_hosts.add(env.server_name)
                                local_hosts.update([
                                    ip[4][0] for ip in socket.getaddrinfo(
                                        env.server_name, 0)])
                        except (socket.gaierror, TypeError):
                            pass
                    global_settings.local_hosts = list(local_hosts)
                else:
                    local_hosts = global_settings.local_hosts
                client = get_client(env)
                x_req_with = str(env.http_x_requested_with).lower()

                request.update(
                    client = client,
                    folder = abspath('applications', app) + os.sep,
                    ajax = x_req_with == 'xmlhttprequest',
                    cid = env.http_web2py_component_element,
                    is_local = env.remote_addr in local_hosts,
                    is_https = env.wsgi_url_scheme in HTTPS_SCHEMES or \
                        request.env.http_x_forwarded_proto in HTTPS_SCHEMES \
                        or env.https == 'on')
                request.compute_uuid()  # requires client
                request.url = environ['PATH_INFO']

                # ##################################################
                # access the requested application
                # ##################################################

                if not exists(request.folder):
                    if app == rwthread.routes.default_application \
                            and app != 'welcome':
                        redirect(URL('welcome', 'default', 'index'))
                    elif rwthread.routes.error_handler:
                        _handler = rwthread.routes.error_handler
                        redirect(URL(_handler['application'],
                                     _handler['controller'],
                                     _handler['function'],
                                     args=app))
                    else:
                        raise HTTP(404, rwthread.routes.error_message
                                   % 'invalid request',
                                   web2py_error='invalid application')
                elif not request.is_local and \
                        exists(pjoin(request.folder, 'DISABLED')):
                    raise HTTP(503, "<html><body><h1>Temporarily down for maintenance</h1></body></html>")

                # ##################################################
                # build missing folders
                # ##################################################

                create_missing_app_folders(request)

                # ##################################################
                # get the GET and POST data
                # ##################################################

                parse_get_post_vars(request, environ)

                # ##################################################
                # expose wsgi hooks for convenience
                # ##################################################

                request.wsgi.environ = environ_aux(environ, request)
                request.wsgi.start_response = \
                    lambda status='200', headers=[], \
                    exec_info=None, response=response: \
                    start_response_aux(status, headers, exec_info, response)
                request.wsgi.middleware = \
                    lambda *a: middleware_aux(request, response, *a)

                # ##################################################
                # load cookies
                # ##################################################

                if env.http_cookie:
                    try:
                        request.cookies.load(env.http_cookie)
                    except Cookie.CookieError, e:
                        pass  # invalid cookies

                # ##################################################
                # try load session or create new session file
                # ##################################################

                if not env.web2py_disable_session:
                    session.connect(request, response)

                # ##################################################
                # run controller
                # ##################################################

                if global_settings.debugging and app != "admin":
                    import gluon.debug
                    # activate the debugger
                    gluon.debug.dbg.do_debug(mainpyfile=request.folder)

                serve_controller(request, response, session)

            except HTTP, http_response:

                if static_file:
                    return http_response.to(responder, env=env)

                if request.body:
                    request.body.close()

                # ##################################################
                # on success, try store session in database
                # ##################################################
                session._try_store_in_db(request, response)

                # ##################################################
                # on success, commit database
                # ##################################################

                if response.do_not_commit is True:
                    BaseAdapter.close_all_instances(None)
                # elif response._custom_commit:
                #     response._custom_commit()
                elif response.custom_commit:
                    BaseAdapter.close_all_instances(response.custom_commit)
                else:
                    BaseAdapter.close_all_instances('commit')

                # ##################################################
                # if session not in db try store session on filesystem
                # this must be done after trying to commit database!
                # ##################################################

                session._try_store_in_cookie_or_file(request, response)

                if request.cid:
                    if response.flash:
                        http_response.headers['web2py-component-flash'] = urllib2.quote(xmlescape(response.flash).replace('\n', ''))
                    if response.js:
                        http_response.headers['web2py-component-command'] = response.js.replace('\n', '')

                # ##################################################
                # store cookies in headers
                # ##################################################

                rcookies = response.cookies
                if session._forget and response.session_id_name in rcookies:
                    del rcookies[response.session_id_name]
                elif session._secure:
                    rcookies[response.session_id_name]['secure'] = True
                http_response.cookies2headers(rcookies)
                ticket = None

            except RestrictedError, e:

                if request.body:
                    request.body.close()

                # ##################################################
                # on application error, rollback database
                # ##################################################

                ticket = e.log(request) or 'unknown'
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')

                http_response = \
                    HTTP(500, rwthread.routes.error_message_ticket %
                         dict(ticket=ticket),
                         web2py_error='ticket %s' % ticket)
Beispiel #37
0
if global_settings.db_sessions is not True:
    global_settings.db_sessions = set()
global_settings.gluon_parent = os.environ.get('web2py_path', os.getcwd())
global_settings.applications_parent = global_settings.gluon_parent
web2py_path = global_settings.applications_parent # backward compatibility
global_settings.app_folders = set()
global_settings.debugging = False

custom_import_install(web2py_path)

create_missing_folders()

# set up logging for subsequent imports
import logging
import logging.config
logpath = abspath("logging.conf")
if os.path.exists(logpath):
    logging.config.fileConfig(abspath("logging.conf"))
else:
    logging.basicConfig()
logger = logging.getLogger("web2py")

from restricted import RestrictedError
from http import HTTP, redirect
from globals import Request, Response, Session
from compileapp import build_environment, run_models_in, \
    run_controller_in, run_view_in
from fileutils import copystream
from contenttype import contenttype
from dal import BaseAdapter
from settings import global_settings
Beispiel #38
0
def wsgibase(environ, responder):
    """
    this is the gluon wsgi application. the first function called when a page
    is requested (static or dynamic). it can be called by paste.httpserver
    or by apache mod_wsgi.

      - fills request with info
      - the environment variables, replacing '.' with '_'
      - adds web2py path and version info
      - compensates for fcgi missing path_info and query_string
      - validates the path in url

    The url path must be either:

    1. for static pages:

      - /<application>/static/<file>

    2. for dynamic pages:

      - /<application>[/<controller>[/<function>[/<sub>]]][.<extension>]
      - (sub may go several levels deep, currently 3 levels are supported:
         sub1/sub2/sub3)

    The naming conventions are:

      - application, controller, function and extension may only contain
        [a-zA-Z0-9_]
      - file and sub may also contain '-', '=', '.' and '/'
    """

    current.__dict__.clear()
    request = Request()
    response = Response()
    session = Session()
    request.env.web2py_path = global_settings.applications_parent
    request.env.web2py_version = web2py_version
    request.env.update(global_settings)
    static_file = False
    try:
        try:
            try:
                # ##################################################
                # handle fcgi missing path_info and query_string
                # select rewrite parameters
                # rewrite incoming URL
                # parse rewritten header variables
                # parse rewritten URL
                # serve file if static
                # ##################################################

                if not environ.get('PATH_INFO',None) and \
                        environ.get('REQUEST_URI',None):
                    # for fcgi, get path_info and query_string from request_uri
                    items = environ['REQUEST_URI'].split('?')
                    environ['PATH_INFO'] = items[0]
                    if len(items) > 1:
                        environ['QUERY_STRING'] = items[1]
                    else:
                        environ['QUERY_STRING'] = ''
                if not environ.get('HTTP_HOST',None):
                    environ['HTTP_HOST'] = '%s:%s' % (environ.get('SERVER_NAME'),
                                                      environ.get('SERVER_PORT'))

                (static_file, environ) = rewrite.url_in(request, environ)
                if static_file:
                    if environ.get('QUERY_STRING', '')[:10] == 'attachment':
                        response.headers['Content-Disposition'] = 'attachment'
                    response.stream(static_file, request=request)

                # ##################################################
                # fill in request items
                # ##################################################

                http_host = request.env.http_host.split(':',1)[0]

                local_hosts = [http_host,'::1','127.0.0.1','::ffff:127.0.0.1']
                if not global_settings.web2py_runtime_gae:
                    local_hosts.append(socket.gethostname())
                    try: local_hosts.append(socket.gethostbyname(http_host))
                    except socket.gaierror: pass
                request.client = get_client(request.env)
                if not is_valid_ip_address(request.client):
                    raise HTTP(400,"Bad Request (request.client=%s)" % \
                                   request.client)
                request.folder = abspath('applications',
                                         request.application) + os.sep
                x_req_with = str(request.env.http_x_requested_with).lower()
                request.ajax = x_req_with == 'xmlhttprequest'
                request.cid = request.env.http_web2py_component_element
                request.is_local = request.env.remote_addr in local_hosts
                request.is_https = request.env.wsgi_url_scheme \
                    in ['https', 'HTTPS'] or request.env.https == 'on'

                # ##################################################
                # compute a request.uuid to be used for tickets and toolbar
                # ##################################################

                response.uuid = request.compute_uuid()

                # ##################################################
                # access the requested application
                # ##################################################

                if not os.path.exists(request.folder):
                    if request.application == \
                            rewrite.thread.routes.default_application \
                            and request.application != 'welcome':
                        request.application = 'welcome'
                        redirect(Url(r=request))
                    elif rewrite.thread.routes.error_handler:
                        _handler = rewrite.thread.routes.error_handler
                        redirect(Url(_handler['application'],
                                     _handler['controller'],
                                     _handler['function'],
                                     args=request.application))
                    else:
                        raise HTTP(404, rewrite.thread.routes.error_message \
                                       % 'invalid request',
                                   web2py_error='invalid application')
                elif not request.is_local and \
                        os.path.exists(os.path.join(request.folder,'DISABLED')):
                    raise HTTP(503, "<html><body><h1>Temporarily down for maintenance</h1></body></html>")
                request.url = Url(r=request, args=request.args,
                                       extension=request.raw_extension)

                # ##################################################
                # build missing folders
                # ##################################################

                create_missing_app_folders(request)

                # ##################################################
                # get the GET and POST data
                # ##################################################

                parse_get_post_vars(request, environ)

                # ##################################################
                # expose wsgi hooks for convenience
                # ##################################################

                request.wsgi.environ = environ_aux(environ,request)
                request.wsgi.start_response = \
                    lambda status='200', headers=[], \
                    exec_info=None, response=response: \
                    start_response_aux(status, headers, exec_info, response)
                request.wsgi.middleware = \
                    lambda *a: middleware_aux(request,response,*a)

                # ##################################################
                # load cookies
                # ##################################################

                if request.env.http_cookie:
                    try:
                        request.cookies.load(request.env.http_cookie)
                    except Cookie.CookieError, e:
                        pass # invalid cookies

                # ##################################################
                # try load session or create new session file
                # ##################################################

                session.connect(request, response)

                # ##################################################
                # set no-cache headers
                # ##################################################

                response.headers['Content-Type'] = \
                    contenttype('.'+request.extension)
                response.headers['Cache-Control'] = \
                    'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
                response.headers['Expires'] = \
                    time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime())
                response.headers['Pragma'] = 'no-cache'

                # ##################################################
                # run controller
                # ##################################################

                if global_settings.debugging and request.application != "admin":
                    import gluon.debug
                    # activate the debugger and wait to reach application code
                    gluon.debug.dbg.do_debug(mainpyfile=request.folder)

                serve_controller(request, response, session)

            except HTTP, http_response:
                if static_file:
                    return http_response.to(responder)

                if request.body:
                    request.body.close()

                # ##################################################
                # on success, try store session in database
                # ##################################################
                session._try_store_in_db(request, response)

                # ##################################################
                # on success, commit database
                # ##################################################

                if response.do_not_commit is True:
                    BaseAdapter.close_all_instances(None)
                # elif response._custom_commit:
                #     response._custom_commit()
                elif response.custom_commit:
                    BaseAdapter.close_all_instances(response.custom_commit)
                else:
                    BaseAdapter.close_all_instances('commit')

                # ##################################################
                # if session not in db try store session on filesystem
                # this must be done after trying to commit database!
                # ##################################################

                session._try_store_on_disk(request, response)

                # ##################################################
                # store cookies in headers
                # ##################################################

                if request.cid:
                    if response.flash and not 'web2py-component-flash' \
                            in http_response.headers:
                        http_response.headers['web2py-component-flash'] = \
                            urllib2.quote(xmlescape(response.flash)\
                                              .replace('\n',''))
                    if response.js and not 'web2py-component-command' \
                            in http_response.headers:
                        http_response.headers['web2py-component-command'] = \
                            response.js.replace('\n','')
                if session._forget and \
                        response.session_id_name in response.cookies:
                    del response.cookies[response.session_id_name]
                elif session._secure:
                    response.cookies[response.session_id_name]['secure'] = True

                http_response.cookies2headers(response.cookies)
                ticket=None

            except RestrictedError, e:

                if request.body:
                    request.body.close()

                # ##################################################
                # on application error, rollback database
                # ##################################################

                ticket = e.log(request) or 'unknown'
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')

                http_response = \
                    HTTP(500, rewrite.thread.routes.error_message_ticket % \
                             dict(ticket=ticket),
                         web2py_error='ticket %s' % ticket)
Beispiel #39
0
def load_routers(all_apps):
    "load-time post-processing of routers"

    for app in routers.keys():
        # initialize apps with routers that aren't present, on behalf of unit tests
        if app not in all_apps:
            all_apps.append(app)
            router = Storage(routers.BASE)   # new copy
            if app != 'BASE':
                for key in routers[app].keys():
                    if key in ROUTER_BASE_KEYS:
                        raise SyntaxError, "BASE-only key '%s' in router '%s'" % (key, app)
            router.update(routers[app])
            routers[app] = router
        router = routers[app]
        for key in router.keys():
            if key not in ROUTER_KEYS:
                raise SyntaxError, "unknown key '%s' in router '%s'" % (key, app)
        if not router.controllers:
            router.controllers = set()
        elif not isinstance(router.controllers, str):
            router.controllers = set(router.controllers)
        if router.languages:
            router.languages = set(router.languages)
        else:
            router.languages = set()
        if app != 'BASE':
            for base_only in ROUTER_BASE_KEYS:
                router.pop(base_only, None)
            if 'domain' in router:
                routers.BASE.domains[router.domain] = app
            if isinstance(router.controllers, str) and router.controllers == 'DEFAULT':
                router.controllers = set()
                if os.path.isdir(abspath('applications', app)):
                    cpath = abspath('applications', app, 'controllers')
                    for cname in os.listdir(cpath):
                        if os.path.isfile(abspath(cpath, cname)) and cname.endswith('.py'):
                            router.controllers.add(cname[:-3])
            if router.controllers:
                router.controllers.add('static')
                router.controllers.add(router.default_controller)
            if router.functions:
                if isinstance(router.functions, (set, tuple, list)):
                    functions = set(router.functions)
                    if isinstance(router.default_function, str):
                        functions.add(router.default_function)  # legacy compatibility
                    router.functions = { router.default_controller: functions }
                for controller in router.functions:
                    router.functions[controller] = set(router.functions[controller])
            else:
                router.functions = dict()

    if isinstance(routers.BASE.applications, str) and routers.BASE.applications == 'ALL':
        routers.BASE.applications = list(all_apps)
    if routers.BASE.applications:
        routers.BASE.applications = set(routers.BASE.applications)
    else:
        routers.BASE.applications = set()

    for app in routers.keys():
        # set router name
        router = routers[app]
        router.name = app
        # compile URL validation patterns
        router._acfe_match = re.compile(router.acfe_match)
        router._file_match = re.compile(router.file_match)
        if router.args_match:
            router._args_match = re.compile(router.args_match)
        # convert path_prefix to a list of path elements
        if router.path_prefix:
            if isinstance(router.path_prefix, str):
                router.path_prefix = router.path_prefix.strip('/').split('/')

    #  rewrite BASE.domains as tuples
    #
    #      key:   'domain[:port]' -> (domain, port)
    #      value: 'application[/controller] -> (application, controller)
    #      (port and controller may be None)
    #
    domains = dict()
    if routers.BASE.domains:
        for (domain, app) in [(d.strip(':'), a.strip('/')) for (d, a) in routers.BASE.domains.items()]:
            port = None
            if ':' in domain:
                (domain, port) = domain.split(':')
            ctlr = None
            fcn = None
            if '/' in app:
                (app, ctlr) = app.split('/', 1)
            if ctlr and '/' in ctlr:
                (ctlr, fcn) = ctlr.split('/')
            if app not in all_apps and app not in routers:
                raise SyntaxError, "unknown app '%s' in domains" % app
            domains[(domain, port)] = (app, ctlr, fcn)
    routers.BASE.domains = domains
Beispiel #40
0
def appfactory(wsgiapp=wsgibase,
               logfilename='httpserver.log',
               profiler_dir=None):
    """
    generates a wsgi application that does logging and profiling and calls
    wsgibase

    .. function:: gluon.main.appfactory(
            [wsgiapp=wsgibase
            [, logfilename='httpserver.log'
            [, profilerfilename='profiler.log']]])

    """

    if profiler_dir:
        profiler_dir = abspath(profiler_dir)
        logger.warn('profiler is on. will use dir %s', profiler_dir)
        if not os.path.isdir(profiler_dir):
            try:
                os.makedirs(profiler_dir)
            except:
                raise BaseException, "Can't create dir %s" % profiler_dir
        filepath = pjoin(profiler_dir, 'wtest')
        try:
            filehandle = open( filepath, 'w' )
            filehandle.close()
            os.unlink(filepath)
        except IOError:
            raise BaseException, "Unable to write to dir %s" % profiler_dir

    def app_with_logging(environ, responder):
        """
        a wsgi app that does logging and profiling and calls wsgibase
        """
        status_headers = []

        def responder2(s, h):
            """
            wsgi responder app
            """
            status_headers.append(s)
            status_headers.append(h)
            return responder(s, h)

        time_in = time.time()
        ret = [0]
        if not profiler_dir:
            ret[0] = wsgiapp(environ, responder2)
        else:
            import cProfile
            prof = cProfile.Profile()
            prof.enable()
            ret[0] = wsgiapp(environ, responder2)
            prof.disable()
            destfile = pjoin(profiler_dir, "req_%s.prof" % web2py_uuid())
            prof.dump_stats(destfile)

        try:
            line = '%s, %s, %s, %s, %s, %s, %f\n' % (
                environ['REMOTE_ADDR'],
                datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S'),
                environ['REQUEST_METHOD'],
                environ['PATH_INFO'].replace(',', '%2C'),
                environ['SERVER_PROTOCOL'],
                (status_headers[0])[:3],
                time.time() - time_in,
            )
            if not logfilename:
                sys.stdout.write(line)
            elif isinstance(logfilename, str):
                write_file(logfilename, line, 'a')
            else:
                logfilename.write(line)
        except:
            pass
        return ret[0]

    return app_with_logging
Beispiel #41
0
custom_import_install(web2py_path)

create_missing_folders()

# set up logging for subsequent imports
import logging
import logging.config

# This needed to prevent exception on Python 2.5:
# NameError: name 'gluon' is not defined
# See http://bugs.python.org/issue1436
import gluon.messageboxhandler
logging.gluon = gluon

logpath = abspath("logging.conf")
if os.path.exists(logpath):
    logging.config.fileConfig(abspath("logging.conf"))
else:
    logging.basicConfig()
logger = logging.getLogger("web2py")

from restricted import RestrictedError
from http import HTTP, redirect
from globals import Request, Response, Session
from compileapp import build_environment, run_models_in, \
    run_controller_in, run_view_in
from fileutils import copystream, parse_version
from contenttype import contenttype
from dal import BaseAdapter
from settings import global_settings
Beispiel #42
0
        routers = params.routers  # establish routers if present
        if isinstance(routers, dict):
            routers = Storage(routers)
        if routers is not None:
            router = _router_default()
            if routers.BASE:
                router.update(routers.BASE)
            routers.BASE = router

        #  scan each app in applications/
        #    create a router, if routers are in use
        #    parse the app-specific routes.py if present
        #
        all_apps = []
        for appname in [
                app for app in os.listdir(abspath('applications'))
                if not app.startswith('.')
        ]:
            if os.path.isdir(abspath('applications', appname)) and \
               os.path.isdir(abspath('applications', appname, 'controllers')):
                all_apps.append(appname)
                if routers:
                    router = Storage(routers.BASE)  # new copy
                    if appname in routers:
                        for key in routers[appname].keys():
                            if key in ROUTER_BASE_KEYS:
                                raise SyntaxError, "BASE-only key '%s' in router '%s'" % (
                                    key, appname)
                        router.update(routers[appname])
                    routers[appname] = router
                if os.path.exists(abspath('applications', appname, routes)):
Beispiel #43
0
def load_routers(all_apps):
    "load-time post-processing of routers"

    for app in routers.keys():
        # initialize apps with routers that aren't present, on behalf of unit tests
        if app not in all_apps:
            all_apps.append(app)
            router = Storage(routers.BASE)  # new copy
            if app != 'BASE':
                for key in routers[app].keys():
                    if key in ROUTER_BASE_KEYS:
                        raise SyntaxError, "BASE-only key '%s' in router '%s'" % (
                            key, app)
            router.update(routers[app])
            routers[app] = router
        router = routers[app]
        for key in router.keys():
            if key not in ROUTER_KEYS:
                raise SyntaxError, "unknown key '%s' in router '%s'" % (key,
                                                                        app)
        if not router.controllers:
            router.controllers = set()
        elif not isinstance(router.controllers, str):
            router.controllers = set(router.controllers)
        if router.languages:
            router.languages = set(router.languages)
        else:
            router.languages = set()
        if router.functions:
            if isinstance(router.functions, (set, tuple, list)):
                functions = set(router.functions)
                if isinstance(router.default_function, str):
                    functions.add(
                        router.default_function)  # legacy compatibility
                router.functions = {router.default_controller: functions}
            for controller in router.functions:
                router.functions[controller] = set(
                    router.functions[controller])
        else:
            router.functions = dict()
        if app != 'BASE':
            for base_only in ROUTER_BASE_KEYS:
                router.pop(base_only, None)
            if 'domain' in router:
                routers.BASE.domains[router.domain] = app
            if isinstance(router.controllers,
                          str) and router.controllers == 'DEFAULT':
                router.controllers = set()
                if os.path.isdir(abspath('applications', app)):
                    cpath = abspath('applications', app, 'controllers')
                    for cname in os.listdir(cpath):
                        if os.path.isfile(abspath(
                                cpath, cname)) and cname.endswith('.py'):
                            router.controllers.add(cname[:-3])
            if router.controllers:
                router.controllers.add('static')
                router.controllers.add(router.default_controller)

    if isinstance(routers.BASE.applications,
                  str) and routers.BASE.applications == 'ALL':
        routers.BASE.applications = list(all_apps)
    if routers.BASE.applications:
        routers.BASE.applications = set(routers.BASE.applications)
    else:
        routers.BASE.applications = set()

    for app in routers.keys():
        # set router name
        router = routers[app]
        router.name = app
        # compile URL validation patterns
        router._acfe_match = re.compile(router.acfe_match)
        router._file_match = re.compile(router.file_match)
        if router.args_match:
            router._args_match = re.compile(router.args_match)
        # convert path_prefix to a list of path elements
        if router.path_prefix:
            if isinstance(router.path_prefix, str):
                router.path_prefix = router.path_prefix.strip('/').split('/')

    #  rewrite BASE.domains as tuples
    #
    #      key:   'domain[:port]' -> (domain, port)
    #      value: 'application[/controller] -> (application, controller)
    #      (port and controller may be None)
    #
    domains = dict()
    if routers.BASE.domains:
        for (domain, app) in [(d.strip(':'), a.strip('/'))
                              for (d, a) in routers.BASE.domains.items()]:
            port = None
            if ':' in domain:
                (domain, port) = domain.split(':')
            ctlr = None
            fcn = None
            if '/' in app:
                (app, ctlr) = app.split('/', 1)
            if ctlr and '/' in ctlr:
                (ctlr, fcn) = ctlr.split('/')
            if app not in all_apps and app not in routers:
                raise SyntaxError, "unknown app '%s' in domains" % app
            domains[(domain, port)] = (app, ctlr, fcn)
    routers.BASE.domains = domains
Beispiel #44
0
create_missing_folders()

# set up logging for subsequent imports
import logging
import logging.config

# This needed to prevent exception on Python 2.5:
# NameError: name 'gluon' is not defined
# See http://bugs.python.org/issue1436
import gluon.messageboxhandler
logging.gluon = gluon

exists = os.path.exists
pjoin = os.path.join

logpath = abspath("logging.conf")
if exists(logpath):
    logging.config.fileConfig(abspath("logging.conf"))
else:
    logging.basicConfig()
logger = logging.getLogger("web2py")

from restricted import RestrictedError
from http import HTTP, redirect
from globals import Request, Response, Session
from compileapp import build_environment, run_models_in, \
    run_controller_in, run_view_in
from contenttype import contenttype
from dal import BaseAdapter
from settings import global_settings
from validators import CRYPT
Beispiel #45
0
def crondance(applications_parent, ctype='soft', startup=False, apps=None):
    apppath = os.path.join(applications_parent, 'applications')
    cron_path = os.path.join(applications_parent)
    token = Token(cron_path)
    cronmaster = token.acquire(startup=startup)
    if not cronmaster:
        return
    now_s = time.localtime()
    checks = (('min', now_s.tm_min),
              ('hr', now_s.tm_hour),
              ('mon', now_s.tm_mon),
              ('dom', now_s.tm_mday),
              ('dow', (now_s.tm_wday + 1) % 7))

    if apps is None:
        apps = [x for x in os.listdir(apppath)
                if os.path.isdir(os.path.join(apppath, x))]

    full_apath_links = set()

    for app in apps:
        if _cron_stopping:
            break
        apath = os.path.join(apppath, app)

        # if app is a symbolic link to other app, skip it
        full_apath_link = absolute_path_link(apath)
        if full_apath_link in full_apath_links:
            continue
        else:
            full_apath_links.add(full_apath_link)

        cronpath = os.path.join(apath, 'cron')
        crontab = os.path.join(cronpath, 'crontab')
        if not os.path.exists(crontab):
            continue
        try:
            cronlines = fileutils.readlines_file(crontab, 'rt')
            lines = [x.strip() for x in cronlines if x.strip(
            ) and not x.strip().startswith('#')]
            tasks = [parsecronline(cline) for cline in lines]
        except Exception, e:
            logger.error('WEB2PY CRON: crontab read error %s' % e)
            continue

        for task in tasks:
            if _cron_stopping:
                break
            commands = [sys.executable]
            w2p_path = fileutils.abspath('web2py.py', gluon=True)
            if os.path.exists(w2p_path):
                commands.append(w2p_path)
            if global_settings.applications_parent != global_settings.gluon_parent:
                commands.extend(('-f', global_settings.applications_parent))
            citems = [(k in task and not v in task[k]) for k, v in checks]
            task_min = task.get('min', [])
            if not task:
                continue
            elif not startup and task_min == [-1]:
                continue
            elif task_min != [-1] and reduce(lambda a, b: a or b, citems):
                continue
            logger.info('WEB2PY CRON (%s): %s executing %s in %s at %s'
                        % (ctype, app, task.get('cmd'),
                           os.getcwd(), datetime.datetime.now()))
            action, command, models = False, task['cmd'], ''
            if command.startswith('**'):
                (action, models, command) = (True, '', command[2:])
            elif command.startswith('*'):
                (action, models, command) = (True, '-M', command[1:])
            else:
                action = False

            if action and command.endswith('.py'):
                commands.extend(('-J',                # cron job
                                 models,              # import models?
                                 '-S', app,           # app name
                                 '-a', '"<recycle>"',  # password
                                 '-R', command))      # command
            elif action:
                commands.extend(('-J',                  # cron job
                                 models,                # import models?
                                 '-S', app + '/' + command,  # app name
                                 '-a', '"<recycle>"'))  # password
            else:
                commands = command

            # from python docs:
            # You do not need shell=True to run a batch file or
            # console-based executable.
            shell = False

            try:
                cronlauncher(commands, shell=shell).start()
            except Exception, e:
                logger.warning(
                    'WEB2PY CRON: Execution error for %s: %s'
                    % (task.get('cmd'), e))
Beispiel #46
0
def wsgibase(environ, responder):
    """
    this is the gluon wsgi application. the first function called when a page
    is requested (static or dynamic). it can be called by paste.httpserver
    or by apache mod_wsgi.

      - fills request with info
      - the environment variables, replacing '.' with '_'
      - adds web2py path and version info
      - compensates for fcgi missing path_info and query_string
      - validates the path in url

    The url path must be either:

    1. for static pages:

      - /<application>/static/<file>

    2. for dynamic pages:

      - /<application>[/<controller>[/<function>[/<sub>]]][.<extension>]
      - (sub may go several levels deep, currently 3 levels are supported:
         sub1/sub2/sub3)

    The naming conventions are:

      - application, controller, function and extension may only contain
        [a-zA-Z0-9_]
      - file and sub may also contain '-', '=', '.' and '/'
    """

    current.__dict__.clear()
    request = Request()
    response = Response()
    session = Session()
    env = request.env
    env.web2py_path = global_settings.applications_parent
    env.web2py_version = web2py_version
    env.update(global_settings)
    static_file = False
    try:
        try:
            try:
                # ##################################################
                # handle fcgi missing path_info and query_string
                # select rewrite parameters
                # rewrite incoming URL
                # parse rewritten header variables
                # parse rewritten URL
                # serve file if static
                # ##################################################

                fixup_missing_path_info(environ)
                (static_file, version, environ) = url_in(request, environ)
                response.status = env.web2py_status_code or response.status

                if static_file:
                    if environ.get('QUERY_STRING',
                                   '').startswith('attachment'):
                        response.headers['Content-Disposition'] \
                            = 'attachment'
                    if version:
                        response.headers['Cache-Control'] = 'max-age=315360000'
                        response.headers[
                            'Expires'] = 'Thu, 31 Dec 2037 23:59:59 GMT'
                    response.stream(static_file, request=request)

                # ##################################################
                # fill in request items
                # ##################################################
                app = request.application  # must go after url_in!

                if not global_settings.local_hosts:
                    local_hosts = set(['127.0.0.1', '::ffff:127.0.0.1', '::1'])
                    if not global_settings.web2py_runtime_gae:
                        try:
                            fqdn = socket.getfqdn()
                            local_hosts.add(socket.gethostname())
                            local_hosts.add(fqdn)
                            local_hosts.update([
                                addrinfo[4][0]
                                for addrinfo in getipaddrinfo(fqdn)
                            ])
                            if env.server_name:
                                local_hosts.add(env.server_name)
                                local_hosts.update([
                                    addrinfo[4][0] for addrinfo in
                                    getipaddrinfo(env.server_name)
                                ])
                        except (socket.gaierror, TypeError):
                            pass
                    global_settings.local_hosts = list(local_hosts)
                else:
                    local_hosts = global_settings.local_hosts
                client = get_client(env)
                x_req_with = str(env.http_x_requested_with).lower()

                request.update(
                    client = client,
                    folder = abspath('applications', app) + os.sep,
                    ajax = x_req_with == 'xmlhttprequest',
                    cid = env.http_web2py_component_element,
                    is_local = env.remote_addr in local_hosts,
                    is_https = env.wsgi_url_scheme in HTTPS_SCHEMES or \
                        request.env.http_x_forwarded_proto in HTTPS_SCHEMES \
                        or env.https == 'on')
                request.compute_uuid()  # requires client
                request.url = environ['PATH_INFO']

                # ##################################################
                # access the requested application
                # ##################################################

                if not exists(request.folder):
                    if app == rwthread.routes.default_application \
                            and app != 'welcome':
                        redirect(URL('welcome', 'default', 'index'))
                    elif rwthread.routes.error_handler:
                        _handler = rwthread.routes.error_handler
                        redirect(
                            URL(_handler['application'],
                                _handler['controller'],
                                _handler['function'],
                                args=app))
                    else:
                        raise HTTP(404,
                                   rwthread.routes.error_message %
                                   'invalid request',
                                   web2py_error='invalid application')
                elif not request.is_local and \
                        exists(pjoin(request.folder, 'DISABLED')):
                    raise HTTP(
                        503,
                        "<html><body><h1>Temporarily down for maintenance</h1></body></html>"
                    )

                # ##################################################
                # build missing folders
                # ##################################################

                create_missing_app_folders(request)

                # ##################################################
                # get the GET and POST data
                # ##################################################

                parse_get_post_vars(request, environ)

                # ##################################################
                # expose wsgi hooks for convenience
                # ##################################################

                request.wsgi.environ = environ_aux(environ, request)
                request.wsgi.start_response = \
                    lambda status='200', headers=[], \
                    exec_info=None, response=response: \
                    start_response_aux(status, headers, exec_info, response)
                request.wsgi.middleware = \
                    lambda *a: middleware_aux(request, response, *a)

                # ##################################################
                # load cookies
                # ##################################################

                if env.http_cookie:
                    try:
                        request.cookies.load(env.http_cookie)
                    except Cookie.CookieError, e:
                        pass  # invalid cookies

                # ##################################################
                # try load session or create new session file
                # ##################################################

                if not env.web2py_disable_session:
                    session.connect(request, response)

                # ##################################################
                # run controller
                # ##################################################

                if global_settings.debugging and app != "admin":
                    import gluon.debug
                    # activate the debugger
                    gluon.debug.dbg.do_debug(mainpyfile=request.folder)

                serve_controller(request, response, session)

            except HTTP, http_response:

                if static_file:
                    return http_response.to(responder, env=env)

                if request.body:
                    request.body.close()

                # ##################################################
                # on success, try store session in database
                # ##################################################
                session._try_store_in_db(request, response)

                # ##################################################
                # on success, commit database
                # ##################################################

                if response.do_not_commit is True:
                    BaseAdapter.close_all_instances(None)
                # elif response._custom_commit:
                #     response._custom_commit()
                elif response.custom_commit:
                    BaseAdapter.close_all_instances(response.custom_commit)
                else:
                    BaseAdapter.close_all_instances('commit')

                # ##################################################
                # if session not in db try store session on filesystem
                # this must be done after trying to commit database!
                # ##################################################

                session._try_store_in_cookie_or_file(request, response)

                if request.cid:
                    if response.flash:
                        http_response.headers['web2py-component-flash'] = \
                            urllib2.quote(xmlescape(response.flash)\
                                              .replace('\n',''))
                    if response.js:
                        http_response.headers['web2py-component-command'] = \
                            urllib2.quote(response.js.replace('\n',''))

                # ##################################################
                # store cookies in headers
                # ##################################################

                rcookies = response.cookies
                if session._forget and response.session_id_name in rcookies:
                    del rcookies[response.session_id_name]
                elif session._secure:
                    rcookies[response.session_id_name]['secure'] = True
                http_response.cookies2headers(rcookies)
                ticket = None

            except RestrictedError, e:

                if request.body:
                    request.body.close()

                # ##################################################
                # on application error, rollback database
                # ##################################################

                ticket = e.log(request) or 'unknown'
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')

                http_response = \
                    HTTP(500, rwthread.routes.error_message_ticket %
                         dict(ticket=ticket),
                         web2py_error='ticket %s' % ticket)
# See <web2py-root-dir>/examples/routes.parametric.example.py for parameter's detail
# ----------------------------------------------------------------------------------------------------------------------

# ----------------------------------------------------------------------------------------------------------------------
# To enable this route file you must do the steps:
# 1. rename <web2py-root-dir>/examples/routes.parametric.example.py to routes.py
# 2. rename this APP/routes.example.py to APP/routes.py (where APP - is your application directory)
# 3. restart web2py (or reload routes in web2py admin interface)
#
# YOU CAN COPY THIS FILE TO ANY APPLICATION'S ROOT DIRECTORY WITHOUT CHANGES!
# ----------------------------------------------------------------------------------------------------------------------

from fileutils import abspath
from languages import read_possible_languages

possible_languages = read_possible_languages(abspath("applications", app))
# ----------------------------------------------------------------------------------------------------------------------
# NOTE! app - is an application based router's parameter with name of an application. E.g.'welcome'
# ----------------------------------------------------------------------------------------------------------------------

routers = {
    app: dict(
        default_language=possible_languages["default"][0],
        languages=[lang for lang in possible_languages if lang != "default"],
    )
}


# ----------------------------------------------------------------------------------------------------------------------
# NOTE! To change language in your application using these rules add this line in one of your models files:
# ----------------------------------------------------------------------------------------------------------------------
Beispiel #48
0
        #
        routers = params.routers    # establish routers if present
        if isinstance(routers, dict):
            routers = Storage(routers)
        if routers is not None:
            router = _router_default()
            if routers.BASE:
                router.update(routers.BASE)
            routers.BASE = router

        #  scan each app in applications/
        #    create a router, if routers are in use
        #    parse the app-specific routes.py if present
        #
        all_apps = []
        for appname in [app for app in os.listdir(abspath('applications')) if not app.startswith('.')]:
            if os.path.isdir(abspath('applications', appname)) and \
               os.path.isdir(abspath('applications', appname, 'controllers')):
                all_apps.append(appname)
                if routers:
                    router = Storage(routers.BASE)   # new copy
                    if appname in routers:
                        for key in routers[appname].keys():
                            if key in ROUTER_BASE_KEYS:
                                raise SyntaxError, "BASE-only key '%s' in router '%s'" % (key, appname)
                        router.update(routers[appname])
                    routers[appname] = router
                if os.path.exists(abspath('applications', appname, routes)):
                    load(routes, appname)

        if routers:
Beispiel #49
0
# To enable this route file you must do the steps:
#
# 1. rename <web2py-root-dir>/router.example.py to routes.py
# 2. rename this APP/routes.example.py to APP/routes.py
#    (where APP - is your application directory)
# 3. restart web2py (or reload routes in web2py admin interfase)
#
# YOU CAN COPY THIS FILE TO ANY APPLICATION'S ROOT DIRECTORY WITHOUT CHANGES!

default_controller = "tasks"
default_function = "index"

from fileutils import abspath
from languages import read_possible_languages

possible_languages = read_possible_languages(abspath('applications', app))
#NOTE! app - is an application based router's parameter with name of an
#            application. E.g.'welcome'

routers = {
    app: dict(
        default_language = possible_languages['default'][0],
        languages = [lang for lang in possible_languages
                           if lang != 'default']
    )
}

#NOTE! To change language in your application using these rules add this line
#in one of your models files:
#   if request.uri_language: T.force(request.uri_language)
Beispiel #50
0
    for sym in ('routes_app', 'routes_in', 'routes_out'):
        if sym in symbols:
            for (k, v) in symbols[sym]:
                p[sym].append(compile_re(k, v))
    for sym in ('routes_onerror', 'routes_apps_raw', 'error_handler',
                'error_message', 'error_message_ticket', 'default_application',
                'default_controller', 'default_function'):
        if sym in symbols:
            p[sym] = symbols[sym]

    if app is None:
        global params
        params = p  # install base rewrite parameters
        for appname in os.listdir('applications'):
            if os.path.exists(abspath('applications', appname, routes)):
                load(routes, appname)
    else:
        params_apps[app] = p
    logger.debug('URL rewrite is on. configuration in %s' % path)


def filter_uri(e, regexes, tag, default=None):
    "filter incoming URI against a list of regexes"
    query = e.get('QUERY_STRING', None)
    path = e['PATH_INFO']
    host = e.get('HTTP_HOST', 'localhost').lower()
    original_uri = path + (query and '?' + query or '')
    i = host.find(':')
    if i > 0:
        host = host[:i]