Example #1
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]
Example #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]
Example #3
0
def create_missing_folders():
    if not global_settings.web2py_runtime_gae:
        for path in ('applications', 'deposit', 'site-packages', 'logs'):
            try_mkdir(abspath(path, gluon=True))
    """
    OLD sys.path dance
    paths = (global_settings.gluon_parent, abspath(
        'site-packages', gluon=True), abspath('gluon', gluon=True), '')
    """
    paths = (global_settings.gluon_parent, abspath(
        'site-packages', gluon=True), '')
    [add_path_first(p) for p in paths]
Example #4
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()
Example #5
0
def unzip(filename, dir, subfolder=''):
    """Unzips filename into dir (.zip only, no .gz etc)

    Args:
        filename(str): archive
        dir(str): destination
        subfolder(str): if != '' unzips 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 += '/'
    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')
Example #6
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()
Example #7
0
    def start(self):
        from gluon import newcron
        import logging
        import logging.config
        from gluon.settings import global_settings
        from gluon.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()
Example #8
0
def upgrade(request, url='http://web2py.com'):
    """Upgrades web2py (src, osx, win) if a new version is posted.
    It detects whether src, osx or win is running and downloads the right one

    Args:
        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
        tuple: completed, traceback

        - completed: True on success, False on failure
          (network problem or old version)
        - traceback: None on success, raised exception details on failure

    """
    web2py_version = request.env.web2py_version
    gluon_parent = request.env.gluon_parent
    if not gluon_parent.endswith('/'):
        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)
    try:
        write_file(filename, urllib.urlopen(full_url).read(), 'wb')
    except Exception as e:
        return False, e
    try:
        unzip(filename, destination, subfolder)
        return True, None
    except Exception as e:
        return False, e
Example #9
0
    def _download_links_write(self):
        """ Write a file to static/ajax/<random number> containing all
            Download Links
        """
        files = []
        for filename in os.listdir(self.BinDir):
            size = os.path.getsize(os.path.join(self.BinDir, filename))
            files.append({'name': filename, 'size': size})
        r = json.dumps(sorted(files))

        # Write info to file
        static_ajax_file = os.path.join(
            abspath(request.folder), "static", "ajax", self.Rand
        )
        mkutils.write_file(static_ajax_file, str(r))
Example #10
0
def change_password():

    if session.pam_user:
        session.flash = T('PAM authenticated user, cannot change password here')
        redirect(URL('site'))
    form=SQLFORM.factory(Field('current_admin_password','password'),
                         Field('new_admin_password','password',requires=IS_STRONG()),
                         Field('new_admin_password_again','password'))
    if form.accepts(request.vars):
        if not verify_password(request.vars.current_admin_password):
            form.errors.current_admin_password = T('invalid password')
        elif form.vars.new_admin_password != form.vars.new_admin_password_again:
            form.errors.new_admin_password_again = T('no match')
        else:
            path = abspath('parameters_%s.py' % request.env.server_port)
            safe_write(path, 'password="******"' % CRYPT()(request.vars.new_admin_password)[0])
            session.flash = T('password changed')
            redirect(URL('site'))
    return dict(form=form)
Example #11
0
def wsgibase(environ, responder):
    """
    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 (or any WSGI-compatible server).

      - 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>]

    The naming conventions are:

      - application, controller, function and extension may only contain
        `[a-zA-Z0-9_]`
      - file and sub may also contain '-', '=', '.' and '/'
    """
    eget = environ.get
    current.__dict__.clear()
    request = Request(environ)
    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
    http_response = None
    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 eget('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()
                cmd_opts = global_settings.cmd_options

                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 and client == env.remote_addr),
                    is_shell=False,
                    is_scheduler=False,
                    is_https=env.wsgi_url_scheme in HTTPS_SCHEMES or
                             request.env.http_x_forwarded_proto in HTTPS_SCHEMES or env.https == 'on'
                    )
                request.url = environ['PATH_INFO']

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

                disabled = pjoin(request.folder, 'DISABLED')
                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(disabled):
                    five0three = os.path.join(request.folder, 'static', '503.html')
                    if os.path.exists(five0three):
                        raise HTTP(503, file(five0three, 'r').read())
                    else:
                        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 = LazyWSGI(environ, request, response)

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

                if env.http_cookie:
                    for single_cookie in env.http_cookie.split(';'):
                        single_cookie = single_cookie.strip()
                        if single_cookie:
                            try:
                                request.cookies.load(single_cookie)
                            except Cookie.CookieError:
                                pass  # single invalid cookie ignore

                # ##################################################
                # 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 as hr:
                http_response = hr

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

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

                if hasattr(current, 'request'):

                    # ##################################################
                    # on success, try store session in database
                    # ##################################################
                    if not env.web2py_disable_session:
                        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:
                        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!
                    # ##################################################
                    if not env.web2py_disable_session:
                        session._try_store_in_cookie_or_file(request, response)

                    # Set header so client can distinguish component requests.
                    if request.cid:
                        http_response.headers.setdefault(
                            'web2py-component-content', 'replace')

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

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

                    session._fixup_before_save()
                    http_response.cookies2headers(response.cookies)

                ticket = None

            except RestrictedError as e:

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

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

                # log tickets before rollback if not in DB
                if not request.tickets_db:
                    ticket = e.log(request) or 'unknown'
                # rollback
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')
                # if tickets in db, reconnect and store it in db
                if request.tickets_db:
                    ticket = e.log(request) or 'unknown'

                http_response = \
                    HTTP(500, rwthread.routes.error_message_ticket %
                         dict(ticket=ticket),
                         web2py_error='ticket %s' % ticket)

        except:

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

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

            try:
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')
            except:
                pass
            e = RestrictedError('Framework', '', '', locals())
            ticket = e.log(request) or 'unrecoverable'
            http_response = \
                HTTP(500, rwthread.routes.error_message_ticket
                     % dict(ticket=ticket),
                     web2py_error='ticket %s' % ticket)

    finally:
        if response and hasattr(response, 'session_file') \
                and response.session_file:
            response.session_file.close()

    session._unlock(response)
    http_response, new_environ = try_rewrite_on_error(
        http_response, request, environ, ticket)
    if not http_response:
        return wsgibase(new_environ, responder)
    if global_settings.web2py_crontype == 'soft':
        newcron.softcron(global_settings.applications_parent).start()
    return http_response.to(responder, env=env)
Example #12
0
def prepare_subfolder(subfolder):
    pth = path.join(abspath(request.folder), subfolder)
    if not path.isdir(pth):
        mkdir(pth)
    return pth
Example #13
0
    def __init__(
        self,
        ip='127.0.0.1',
        port=8000,
        password='',
        pid_filename='httpserver.pid',
        log_filename='httpserver.log',
        profiler_dir=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, list):
                for i in interfaces:
                    if not isinstance(i, tuple):
                        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)
            load_routes()
            for p in (path, abspath('site-packages'), ""):
                add_path_first(p)
            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.has_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_dir)}

        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,
                                    )
Example #14
0
def appfactory(wsgiapp=wsgibase,
               logfilename='httpserver.log',
               profiler_dir=None,
               profilerfilename=None):
    """
    generates a wsgi application that does logging and profiling and calls
    wsgibase

    Args:
        wsgiapp: the base application
        logfilename: where to store apache-compatible requests log
        profiler_dir: where to store profile files

    """
    if profilerfilename is not None:
        raise BaseException("Deprecated API")
    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
Example #15
0
def appfactory(wsgiapp=wsgibase,
               logfilename='httpserver.log',
               profiler_dir=None,
               profilerfilename=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 profilerfilename is not None:
        raise BaseException("Deprecated API")
    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
Example #16
0
    def __init__(
        self,
        ip='127.0.0.1',
        port=8000,
        password='',
        pid_filename='httpserver.pid',
        log_filename='httpserver.log',
        profiler_dir=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_dir)}

        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,
                                    )
Example #17
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 '/'
    """
    eget = environ.get
    current.__dict__.clear()
    request = Request(environ)
    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 eget('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
                # ##################################################

                disabled = pjoin(request.folder, 'DISABLED')
                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(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 = LazyWSGI(environ, request, response)

                # ##################################################
                # 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()

                if hasattr(current,'request'):

                    # ##################################################
                    # 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:
                        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)

                    # Set header so client can distinguish component requests.
                    if request.cid:
                        http_response.headers.setdefault(
                            'web2py-component-content', 'replace')

                    if request.ajax:
                        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
                    # ##################################################

                    session._fixup_before_save()
                    http_response.cookies2headers(response.cookies)

                ticket = None

            except RestrictedError, e:

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

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

                # log tickets before rollback if not in DB
                if not request.tickets_db:
                    ticket = e.log(request) or 'unknown'
                # rollback
                if response._custom_rollback:
                    response._custom_rollback()
                else:
                    BaseAdapter.close_all_instances('rollback')
                # if tickets in db, reconnect and store it in db
                if request.tickets_db:
                    ticket = e.log(request) or 'unknown'

                http_response = \
                    HTTP(500, rwthread.routes.error_message_ticket %
                         dict(ticket=ticket),
                         web2py_error='ticket %s' % ticket)
Example #18
0
# 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 gluon.fileutils import abspath
from gluon.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)
Example #19
0
def crondance(applications_parent, ctype='soft', startup=False, apps=None):
    apppath = os.path.join(applications_parent, 'applications')
    token = Token(applications_parent)
    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 = [
                line.strip()
                for line in fileutils.readlines_file(crontab, 'rt')
            ]
            lines = [
                line for line in cronlines if line and not line.startswith('#')
            ]
            tasks = [parsecronline(cline) for cline in lines]
        except Exception as 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 as e:
                logger.warning('WEB2PY CRON: Execution error for %s: %s' %
                               (task.get('cmd'), e))
    token.release()
Example #20
0
# This needed to prevent exception on Python 2.5:
# NameError: name 'gluon' is not defined
# See http://bugs.python.org/issue1436

# attention!, the import Tkinter in messageboxhandler, changes locale ...
import gluon.messageboxhandler
logging.gluon = gluon
# so we must restore it! Thanks ozancag
import locale
locale.setlocale(locale.LC_CTYPE, "C") # IMPORTANT, web2py requires locale "C"

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 gluon.restricted import RestrictedError
from gluon.http import HTTP, redirect
from gluon.globals import Request, Response, Session
from gluon.compileapp import build_environment, run_models_in, \
    run_controller_in, run_view_in
from gluon.contenttype import contenttype
from gluon.dal import BaseAdapter
from gluon.validators import CRYPT
from gluon.html import URL, xmlescape
Example #21
0
def crondance(applications_parent, ctype='soft', startup=False, apps=None):
    # TODO: docstring
    apppath = os.path.join(applications_parent, 'applications')
    token = Token(applications_parent)
    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()

    if sys.executable.lower().endswith('pythonservice.exe'):
        _python_exe = os.path.join(sys.exec_prefix, 'python.exe')
    else:
        _python_exe = sys.executable
    base_commands = [_python_exe]
    w2p_path = fileutils.abspath('web2py.py', gluon=True)
    if os.path.exists(w2p_path):
        base_commands.append(w2p_path)
    if applications_parent != global_settings.gluon_parent:
        base_commands.extend(('-f', applications_parent))
    base_commands.extend(('-J',
                          # FIXME: this should not be needed since we are
                          #        not launching the web server
                          '-a', '"<recycle>"'))

    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 = [line.strip() for line in fileutils.readlines_file(crontab, 'rt')]
            lines = [line for line in cronlines if line and not line.startswith('#')]
            tasks = [parsecronline(cline) for cline in lines]
        except Exception as e:
            logger.error('crontab read error %s', e)
            continue

        for task in tasks:
            if _cron_stopping:
                break
            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('%s cron: %s executing %s in %s at %s',
                ctype, app, task.get('cmd'),
                os.getcwd(), datetime.datetime.now())
            action = models = False
            command = task['cmd']
            if command.startswith('**'):
                action = True
                command = command[2:]
            elif command.startswith('*'):
                action = models = True
                command = command[1:]

            if action:
                commands = base_commands[:]
                if command.endswith('.py'):
                    commands.extend(('-S', app, '-R', command))
                else:
                    commands.extend(('-S', app + '/' + command))
                if models:
                    commands.append('-M')
            else:
                commands = command

            try:
                cronlauncher(commands).start()
            except Exception as e:
                logger.warning('execution error for %s: %s',
                    task.get('cmd'), e)
    token.release()
Example #22
0
def crondance(applications_parent, ctype='soft', startup=False, apps=None):
    """
    Does the periodic job of cron service: read the crontab(s) and launch
    the various commands.
    """
    apppath = os.path.join(applications_parent, 'applications')
    token = Token(applications_parent)
    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))

    logger = getLogger(logger_name)

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

    full_apath_links = set()

    if sys.executable.lower().endswith('pythonservice.exe'):
        _python_exe = os.path.join(sys.exec_prefix, 'python.exe')
    else:
        _python_exe = sys.executable
    base_commands = [_python_exe]
    w2p_path = fileutils.abspath('web2py.py', gluon=True)
    if os.path.exists(w2p_path):
        base_commands.append(w2p_path)
    if applications_parent != global_settings.gluon_parent:
        base_commands.extend(('-f', applications_parent))
    base_commands.extend(('--cron_job', '--no_banner', '--no_gui', '--plain'))

    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 = [line.strip() for line in fileutils.readlines_file(crontab, 'rt')]
            lines = [line for line in cronlines if line and not line.startswith('#')]
            tasks = [parsecronline(cline) for cline in lines]
        except Exception as e:
            logger.error('crontab read error %s', e)
            continue

        for task in tasks:
            if _cron_stopping:
                break
            if not task:
                continue
            task_min = task.get('min', [])
            if not startup and task_min == [-1]:
                continue
            citems = [(k in task and not v in task[k]) for k, v in checks]
            if task_min != [-1] and reduce(lambda a, b: a or b, citems):
                continue

            logger.info('%s cron: %s executing %r in %s at %s',
                ctype, app, task.get('cmd'),
                os.getcwd(), datetime.datetime.now())
            action = models = False
            command = task['cmd']
            if command.startswith('**'):
                action = True
                command = command[2:]
            elif command.startswith('*'):
                action = models = True
                command = command[1:]

            if action:
                commands = base_commands[:]
                if command.endswith('.py'):
                    commands.extend(('-S', app, '-R', command))
                else:
                    commands.extend(('-S', app + '/' + command))
                if models:
                    commands.append('-M')
            else:
                commands = shlex.split(command)

            try:
                # FIXME: using a new thread every time there is a task to
                #        launch is not a good idea in a long running process
                cronlauncher(commands).start()
            except Exception:
                logger.exception('error starting %r', task['cmd'])
    token.release()
Example #23
0
# This needed to prevent exception on Python 2.5:
# NameError: name 'gluon' is not defined
# See http://bugs.python.org/issue1436

# attention!, the import Tkinter in messageboxhandler, changes locale ...
import gluon.messageboxhandler
logging.gluon = gluon
# so we must restore it! Thanks ozancag
import locale
locale.setlocale(locale.LC_CTYPE, "C")  # IMPORTANT, web2py requires locale "C"

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

try:
    logging.config.fileConfig(abspath("logging.conf"))
except:  # fails on GAE or when logfile is missing
    logging.basicConfig()
logger = logging.getLogger("web2py")

from gluon.restricted import RestrictedError
from gluon.http import HTTP, redirect
from gluon.globals import Request, Response, Session
from gluon.compileapp import build_environment, run_models_in, \
    run_controller_in, run_view_in
from gluon.contenttype import contenttype
from pydal.base import BaseAdapter
from gluon.validators import CRYPT
from gluon.html import URL, xmlescape
from gluon.utils import is_valid_ip_address, getipaddrinfo
from gluon.rewrite import load as load_routes, url_in, THREAD_LOCAL as rwthread, \
Example #24
0
def run_controller_in(controller, function, environment):
    """
    Runs the controller.function() (for the app specified by
    the current folder).
    It tries pre-compiled controller.function.pyc first before compiling it.
    """
    # if compiled should run compiled!
    folder = current.request.folder
    cpath = pjoin(folder, 'compiled')
    badc = 'invalid controller (%s/%s)' % (controller, function)
    badf = 'invalid function (%s/%s)' % (controller, function)
    if exists(cpath):
        filename = pjoin(cpath, 'controllers.%s.%s.pyc' % (controller, function))
        try:
            ccode = getcfs(filename, filename, lambda: read_pyc(filename))
        except IOError:
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badf,
                       web2py_error=badf)
    elif function == '_TEST':
        # TESTING: adjust the path to include site packages
        paths = (global_settings.gluon_parent, abspath(
            'site-packages', gluon=True), abspath('gluon', gluon=True), '')
        [add_path_first(path) for path in paths]
        # TESTING END

        filename = pjoin(folder, 'controllers/%s.py'
                                 % controller)
        if not exists(filename):
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badc,
                       web2py_error=badc)
        environment['__symbols__'] = list(environment.keys())
        code = read_file(filename)
        code += TEST_CODE
        ccode = compile2(code, filename)
    else:
        filename = pjoin(folder, 'controllers/%s.py' % controller)
        try:
            code = getcfs(filename, filename, lambda: read_file(filename))
        except IOError:
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badc,
                       web2py_error=badc)
        exposed = find_exposed_functions(code)
        if function not in exposed:
            raise HTTP(404,
                       rewrite.THREAD_LOCAL.routes.error_message % badf,
                       web2py_error=badf)
        code = "%s\nresponse._vars=response._caller(%s)" % (code, function)
        layer = "%s:%s" % (filename, function)
        ccode = getcfs(layer, filename, lambda: compile2(code, filename))

    restricted(ccode, environment, layer=filename)
    response = environment["response"]
    vars = response._vars
    if response.postprocessing:
        vars = reduce(lambda vars, p: p(vars), response.postprocessing, vars)
    if isinstance(vars, unicodeT):
        vars = to_native(vars)
    elif hasattr(vars, 'xml') and callable(vars.xml):
        vars = vars.xml()
    return vars
Example #25
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 as 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 as e:
                logger.warning(
                    'WEB2PY CRON: Execution error for %s: %s'
                    % (task.get('cmd'), e))
    token.release()