def index(): form = SQLFORM(db.converter) if form.validate(): path_src_dest = request.folder + 'uploads/' dest_ext = '.' + form.vars.convert_to source_uuid_name = form.vars.upload_input_file dest_uuid_name = form.vars.upload_input_file + '.' + form.vars.convert_to try: process = check_output('convert {0} {0}{1}' .format(path_src_dest + source_uuid_name, dest_ext), shell=True, stderr=STDOUT) except CalledProcessError: response.flash = "couldn't process file, internal error" items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*').match(source_uuid_name) (t, f) = (items.group('table'), items.group('field')) field = db[t][f] (source_orig_name, stream) = field.retrieve(source_uuid_name,nameonly=True) print source_orig_name, dest_uuid_name print '**', path_src_dest + dest_uuid_name if os.path.isfile(path_src_dest + dest_uuid_name): os.rename(path_src_dest + dest_uuid_name, path_src_dest + source_orig_name[:source_orig_name.rfind('.')] + dest_ext) dest_name = source_orig_name[:source_orig_name.rfind('.')] + dest_ext renamed_file_path=os.path.join(path_src_dest, dest_name) print dest_name #response.headers['ContentType'] ="image/jpeg"; response.headers['ContentType'] =contenttype(dest_name); print contenttype(dest_name) response.headers['Content-Disposition']="attachment; filename=" +dest_name return response.stream(open(renamed_file_path),chunk_size=4096) return dict(form=form)
def stream( self, stream, chunk_size=10**6, request=None, ): """ if a controller function > return response.stream(file,100) the file content will be streamed at 100 bytes at the time """ if isinstance(stream, str): stream_file_or_304_or_206(stream, request=request, chunk_size=chunk_size, headers=self.headers) # ## the following is for backward compatibility if hasattr(stream, 'name'): filename = stream.name else: filename = None keys = [item.lower() for item in self.headers.keys()] if filename and not 'content-type' in keys: self.headers['Content-Type'] = contenttype(filename) if filename and not 'content-length' in keys: self.headers['Content-Length'] = \ os.stat(filename)[stat.ST_SIZE] self.body = streamer(stream, chunk_size) return self.body
def download_or(): whois=request.args(0) alg = (str(db(db.uplds.id==whois).select())).split('uplds.algorithm_sharing')[1] alg = alg.split('\n')[1] alg = alg.split('\r')[0] algo = [] algo = alg.split(',') if (algo[4] == 'public'): os.chdir('/var/www/web2py/applications/milo/modules/algorithms/recsys_matlab_codes/algorithms/public/') filename = "onLineRecom_" + algo[1] + ".m" if (algo[4] == 'private'): os.chdir('/var/www/web2py/applications/milo/modules/algorithms/recsys_matlab_codes/algorithms/private/') filename = "onLineRecom_" + algo[1] + ".m" print '\ndownloading: ' + filename #download or s=cStringIO.StringIO() file=open(filename) s.write(file.read()) response.headers['Content-Type'] = c.contenttype(filename) response.headers['Content-Disposition'] = \ "attachment; filename=%s" % filename os.chdir('/var/www/web2py') return s.getvalue()
def stream( self, stream, chunk_size=10 ** 6, request=None, ): """ if a controller function > return response.stream(file,100) the file content will be streamed at 100 bytes at the time """ if isinstance(stream, str): stream_file_or_304_or_206(stream, request=request, chunk_size=chunk_size, headers=self.headers) # ## the following is for backward compatibility if hasattr(stream, 'name'): filename = stream.name else: filename = None keys = [item.lower() for item in self.headers.keys()] if filename and not 'content-type' in keys: self.headers['Content-Type'] = contenttype(filename) if filename and not 'content-length' in keys: self.headers['Content-Length'] = \ os.stat(filename)[stat.ST_SIZE] self.body = streamer(stream, chunk_size) return self.body
def download(self, request, db, chunk_size=DEFAULT_CHUNK_SIZE, attachment=True): """ example of usage in controller:: def download(): return response.download(request, db) downloads from http://..../download/filename """ if not request.args: raise HTTP(404) name = request.args[-1] items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*')\ .match(name) if not items: raise HTTP(404) (t, f) = (items.group('table'), items.group('field')) field = db[t][f] try: (filename, stream) = field.retrieve(name) except IOError: raise HTTP(404) headers = self.headers headers['Content-Type'] = contenttype(name) if attachment: headers['Content-Disposition'] = \ 'attachment; filename=%s' % filename return self.stream(stream, chunk_size=chunk_size, request=request)
def download(self, request, db, chunk_size=DEFAULT_CHUNK_SIZE, attachment=True): """ example of usage in controller:: def download(): return response.download(request, db) downloads from http://..../download/filename """ import contenttype as c if not request.args: raise HTTP(404) name = request.args[-1] items = re.compile("(?P<table>.*?)\.(?P<field>.*?)\..*").match(name) if not items: raise HTTP(404) (t, f) = (items.group("table"), items.group("field")) field = db[t][f] try: (filename, stream) = field.retrieve(name) except IOError: raise HTTP(404) self.headers["Content-Type"] = c.contenttype(name) if attachment: self.headers["Content-Disposition"] = "attachment; filename=%s" % filename return self.stream(stream, chunk_size=chunk_size, request=request)
def download(self, request, db, chunk_size=DEFAULT_CHUNK_SIZE, attachment=True, download_filename=None): """ example of usage in controller:: def download(): return response.download(request, db) downloads from http://..../download/filename """ current.session.forget(current.response) if not request.args: raise HTTP(404) name = request.args[-1] items = re.compile("(?P<table>.*?)\.(?P<field>.*?)\..*").match(name) if not items: raise HTTP(404) (t, f) = (items.group("table"), items.group("field")) try: field = db[t][f] except AttributeError: raise HTTP(404) try: (filename, stream) = field.retrieve(name, nameonly=True) except IOError: raise HTTP(404) headers = self.headers headers["Content-Type"] = contenttype(name) if download_filename == None: download_filename = filename if attachment: headers["Content-Disposition"] = 'attachment; filename="%s"' % download_filename.replace('"', '"') return self.stream(stream, chunk_size=chunk_size, request=request)
def stream(self, stream, chunk_size=DEFAULT_CHUNK_SIZE, request=None, attachment=False, filename=None): """ if a controller function:: return response.stream(file, 100) the file content will be streamed at 100 bytes at the time Optional kwargs: (for custom stream calls) attachment=True # Send as attachment. Usually creates a # pop-up download window on browsers filename=None # The name for the attachment Note: for using the stream name (filename) with attachments the option must be explicitly set as function parameter(will default to the last request argument otherwise) """ # for attachment settings and backward compatibility keys = [item.lower() for item in self.headers] if attachment: if filename is None: attname = "" else: attname = filename self.headers["Content-Disposition"] = "attachment;filename=%s" % attname if not request: request = current.request if isinstance(stream, (str, unicode)): stream_file_or_304_or_206(stream, chunk_size=chunk_size, request=request, headers=self.headers) # ## the following is for backward compatibility if hasattr(stream, "name"): filename = stream.name if filename and not "content-type" in keys: self.headers["Content-Type"] = contenttype(filename) if filename and not "content-length" in keys: try: self.headers["Content-Length"] = os.path.getsize(filename) except OSError: pass # Internet Explorer < 9.0 will not allow downloads over SSL unless caching is enabled if ( request.is_https and isinstance(request.env.http_user_agent, str) and not re.search(r"Opera", request.env.http_user_agent) and re.search(r"MSIE [5-8][^0-9]", request.env.http_user_agent) ): self.headers["Pragma"] = "cache" self.headers["Cache-Control"] = "private" if request and request.env.web2py_use_wsgi_file_wrapper: wrapped = request.env.wsgi_file_wrapper(stream, chunk_size) else: wrapped = streamer(stream, chunk_size=chunk_size) return wrapped
def download(self, request, db, chunk_size=DEFAULT_CHUNK_SIZE, attachment=True): """ example of usage in controller:: def download(): return response.download(request, db) downloads from http://..../download/filename """ if not request.args: raise HTTP(404) name = request.args[-1] items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*')\ .match(name) if not items: raise HTTP(404) (t, f) = (items.group('table'), items.group('field')) try: field = db[t][f] except AttributeError: raise HTTP(404) try: (filename, stream) = field.retrieve(name) except IOError: raise HTTP(404) headers = self.headers headers['Content-Type'] = contenttype(name) if attachment: headers['Content-Disposition'] = \ 'attachment; filename=%s' % filename return self.stream(stream, chunk_size=chunk_size, request=request)
def stream(self, stream, chunk_size=DEFAULT_CHUNK_SIZE, request=None): """ if a controller function:: return response.stream(file, 100) the file content will be streamed at 100 bytes at the time """ if isinstance(stream, (str, unicode)): stream_file_or_304_or_206(stream, chunk_size=chunk_size, request=request, headers=self.headers) # ## the following is for backward compatibility if hasattr(stream, "name"): filename = stream.name else: filename = None keys = [item.lower() for item in self.headers] if filename and not "content-type" in keys: self.headers["Content-Type"] = contenttype(filename) if filename and not "content-length" in keys: try: self.headers["Content-Length"] = os.path.getsize(filename) except OSError: pass if request and request.env.web2py_use_wsgi_file_wrapper: wrapped = request.env.wsgi_file_wrapper(stream, chunk_size) else: wrapped = streamer(stream, chunk_size=chunk_size) return wrapped
def serve_controller(request, response, session): """ this function is used to generate a dynamic page. It first runs all models, then runs the function in the controller, and then tries to render the output using a view/template. this function must run from the [application] folder. A typical example would be the call to the url /[application]/[controller]/[function] that would result in a call to [function]() in applications/[application]/[controller].py rendered by applications/[application]/views/[controller]/[function].html """ # ################################################## # build environment for controller and view # ################################################## environment = build_environment(request, response, session) # set default view, controller can override it response.view = '%s/%s.%s' % (request.controller, request.function, request.extension) # also, make sure the flash is passed through # ################################################## # process models, controller and view (if required) # ################################################## run_models_in(environment) response._view_environment = copy.copy(environment) page = run_controller_in(request.controller, request.function, environment) if isinstance(page, dict): response._vars = page response._view_environment.update(page) run_view_in(response._view_environment) page = response.body.getvalue() # logic to garbage collect after exec, not always, once every 100 requests global requests requests = ('requests' in globals()) and (requests + 1) % 100 or 0 if not requests: gc.collect() # end garbage collection logic # ################################################## # set default headers it not set # ################################################## default_headers = [ ('Content-Type', contenttype('.' + request.extension)), ('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'), ('Expires', time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime())), ('Pragma', 'no-cache')] for key, value in default_headers: response.headers.setdefault(key, value) raise HTTP(response.status, page, **response.headers)
def download_pdf(): file_id = 2 import cStringIO import contenttype as c s=cStringIO.StringIO() (filename,file) = db.info.archivo.retrieve(db.info[file_id].archivo) s.write(file.read()) response.headers['Content-Type'] = c.contenttype(filename) response.headers['Content-Disposition'] = \ "attachment; filename=%s" % filename return s.getvalue()
def testTypeRecognition(self): rtn = contenttype('.png') self.assertEqual(rtn, 'image/png') rtn = contenttype('.gif') self.assertEqual(rtn, 'image/gif') rtn = contenttype('.tar.bz2') self.assertEqual(rtn, 'application/x-bzip-compressed-tar') # test overrides and additions mapping = { '.load': 'text/html; charset=utf-8', '.json': 'application/json', '.jsonp': 'application/jsonp', '.pickle': 'application/python-pickle', '.w2p': 'application/w2p', '.md': 'text/x-markdown; charset=utf-8' } for k, v in mapping.iteritems(): self.assertEqual(contenttype(k), v) # test without dot extension rtn = contenttype('png') self.assertEqual(rtn, 'text/plain; charset=utf-8')
def attachment_download(): if not request.args(0) or not request.args[0].isdigit(): raise HTTP(404) id = int(request.args[0]) import cStringIO import contenttype as c s=cStringIO.StringIO() (filename,file) = db.attachments.attachment.retrieve(db.attachments[id].attachment) s.write(file.read()) response.headers['Content-Type'] = c.contenttype(filename) response.headers['Content-Disposition'] = "attachment; filename=%s" % filename return s.getvalue()
def download_all(): if len(request.args) == 0: redirect(URL('default', 'index')) assignmentId = int(request.args[0]) asgn_info = get_assignment(db, assignmentId) tmpfilepath = zip_assignment(db, asgn_info) response.headers['Content-Type'] = contenttype.contenttype(tmpfilepath) response.headers['Content-Disposition'] = 'attachment; filename={0}.zip'.format(asgn_info['name']) return response.stream(open(tmpfilepath,'rb'),chunk_size=4096)
def doc(): import re import contenttype items = re.compile('(?P<id>.*?)\.(?P<ext>\w*)').match(request.args(0) or '') if not items: raise HTTP(404) (id, ext) = (items.group('id'), items.group('ext')) name = db.cms_file(id).file (filename, stream) = db.cms_file.file.retrieve(name) print filename file = db.cms_file(id) response.headers['Content-Type'] = contenttype.contenttype(name) response.headers['Content-Disposition'] = "attachment; filename=%s" % filename return response.stream(stream, request=request)
def stream( self, stream, chunk_size = DEFAULT_CHUNK_SIZE, request=None, ): """ if a controller function:: return response.stream(file, 100) the file content will be streamed at 100 bytes at the time """ if not request: request = current.request if isinstance(stream, (str, unicode)): stream_file_or_304_or_206(stream, chunk_size=chunk_size, request=request, headers=self.headers) # ## the following is for backward compatibility if hasattr(stream, 'name'): filename = stream.name else: filename = None keys = [item.lower() for item in self.headers] if filename and not 'content-type' in keys: self.headers['Content-Type'] = contenttype(filename) if filename and not 'content-length' in keys: try: self.headers['Content-Length'] = \ os.path.getsize(filename) except OSError: pass # Internet Explorer < 9.0 will not allow downloads over SSL unless caching is enabled if request.is_https and isinstance(request.env.http_user_agent,str) and \ not re.search(r'Opera', request.env.http_user_agent) and \ re.search(r'MSIE [5-8][^0-9]', request.env.http_user_agent): self.headers['Pragma'] = 'cache' self.headers['Cache-Control'] = 'private' if request and request.env.web2py_use_wsgi_file_wrapper: wrapped = request.env.wsgi_file_wrapper(stream, chunk_size) else: wrapped = streamer(stream, chunk_size=chunk_size) return wrapped
def stream( self, stream, chunk_size=DEFAULT_CHUNK_SIZE, request=None, ): """ if a controller function:: return response.stream(file, 100) the file content will be streamed at 100 bytes at the time """ if not request: request = current.request if isinstance(stream, (str, unicode)): stream_file_or_304_or_206(stream, chunk_size=chunk_size, request=request, headers=self.headers) # ## the following is for backward compatibility if hasattr(stream, 'name'): filename = stream.name else: filename = None keys = [item.lower() for item in self.headers] if filename and not 'content-type' in keys: self.headers['Content-Type'] = contenttype(filename) if filename and not 'content-length' in keys: try: self.headers['Content-Length'] = \ os.path.getsize(filename) except OSError: pass # Internet Explorer < 9.0 will not allow downloads over SSL unless caching is enabled if request.is_https and isinstance(request.env.http_user_agent,str) and \ not re.search(r'Opera', request.env.http_user_agent) and \ re.search(r'MSIE [5-8][^0-9]', request.env.http_user_agent): self.headers['Pragma'] = 'cache' self.headers['Cache-Control'] = 'private' if request and request.env.web2py_use_wsgi_file_wrapper: wrapped = request.env.wsgi_file_wrapper(stream, chunk_size) else: wrapped = streamer(stream, chunk_size=chunk_size) return wrapped
def download_template(): import cStringIO import contenttype as c file_id = request.args(0) s = cStringIO.StringIO() (filename, file) = db.t_seq_config_template.f_file.retrieve( db.t_seq_config_template[file_id].f_file) s.write(file.read()) response.headers['Content-Type'] = c.contenttype(filename) response.headers['Content-Disposition'] = \ "attachment; filename=%s" % filename return s.getvalue()
def doc(): import re import contenttype items = re.compile('(?P<id>.*?)\.(?P<ext>\w*)').match( request.args(0) or '') if not items: raise HTTP(404) (id, ext) = (items.group('id'), items.group('ext')) name = db.cms_file(id).file (filename, stream) = db.cms_file.file.retrieve(name) print filename file = db.cms_file(id) response.headers['Content-Type'] = contenttype.contenttype(name) response.headers[ 'Content-Disposition'] = "attachment; filename=%s" % filename return response.stream(stream, request=request)
def download_defor(): whois=request.args(0) os.chdir('/var/www/web2py/applications/milo/modules/algorithms/recsys_matlab_codes/algorithms/default/') filename = "onLineRecom_" + whois + '.m' print '\ndownloading: ' + filename #download mc s=cStringIO.StringIO() file=open(filename) s.write(file.read()) response.headers['Content-Type'] = c.contenttype(filename) response.headers['Content-Disposition'] = \ "attachment; filename=%s" % filename os.chdir('/var/www/web2py') return s.getvalue()
def stream_file_or_304_or_206( static_file, chunk_size=10**6, request=None, headers={}, error_message=error_message, ): if not os.path.exists(static_file): raise HTTP(404, error_message, web2py_error='invalid file') stat_file = os.stat(static_file) fsize = stat_file[stat.ST_SIZE] mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(stat_file[stat.ST_MTIME])) headers['Content-Type'] = contenttype(static_file) headers['Last-Modified'] = mtime headers['Pragma'] = 'cache' headers['Cache-Control'] = 'private' if request and request.env.http_if_modified_since == mtime: raise HTTP(304) elif request and request.env.http_range: start_items = regex_start_range.findall(request.env.http_range) if not start_items: start_items = [0] stop_items = regex_stop_range.findall(request.env.http_range) if not stop_items or int(stop_items[0]) > fsize - 1: stop_items = [fsize - 1] part = (int(start_items[0]), int(stop_items[0]), fsize) bytes = part[1] - part[0] + 1 try: stream = open(static_file, 'rb') except IOError: raise HTTP(404) stream.seek(part[0]) headers['Content-Range'] = 'bytes %i-%i/%i' % part headers['Content-Length'] = '%i' % bytes raise HTTP(206, streamer(stream, chunk_size=chunk_size, bytes=bytes), **headers) else: try: stream = open(static_file, 'rb') except IOError: raise HTTP(404) headers['Content-Length'] = fsize raise HTTP(200, streamer(stream, chunk_size=chunk_size), **headers)
def f(_action=action, _self=self, *a, **b): self.is_restful = True method = _self.env.request_method if len(_self.args) and "." in _self.args[-1]: _self.args[-1], _self.extension = _self.args[-1].rsplit(".", 1) current.response.headers["Content-Type"] = contenttype(_self.extension.lower()) if not method in ["GET", "POST", "DELETE", "PUT"]: raise HTTP(400, "invalid method") rest_action = _action().get(method, None) if not rest_action: raise HTTP(400, "method not supported") try: return rest_action(*_self.args, **_self.vars) except TypeError, e: exc_type, exc_value, exc_traceback = sys.exc_info() if len(traceback.extract_tb(exc_traceback)) == 1: raise HTTP(400, "invalid arguments") else: raise e
def f(_action=action, _self=self, *a, **b): self.is_restful = True method = _self.env.request_method if len(_self.args) and '.' in _self.args[-1]: _self.args[-1], _, self.extension = self.args[-1].rpartition('.') current.response.headers['Content-Type'] = \ contenttype('.' + _self.extension.lower()) if not method in ['GET', 'POST', 'DELETE', 'PUT']: raise HTTP(400, "invalid method") rest_action = _action().get(method, None) if not rest_action: raise HTTP(400, "method not supported") try: return rest_action(*_self.args, **_self.vars) except TypeError, e: exc_type, exc_value, exc_traceback = sys.exc_info() if len(traceback.extract_tb(exc_traceback)) == 1: raise HTTP(400, "invalid arguments") else: raise e
def download(self, request, db, chunk_size=DEFAULT_CHUNK_SIZE, attachment=True, download_filename=None): """ example of usage in controller:: def download(): return response.download(request, db) downloads from http://..../download/filename """ current.session.forget(current.response) if not request.args: raise HTTP(404) name = request.args[-1] items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*')\ .match(name) if not items: raise HTTP(404) (t, f) = (items.group('table'), items.group('field')) try: field = db[t][f] except AttributeError: raise HTTP(404) try: (filename, stream) = field.retrieve(name, nameonly=True) except IOError: raise HTTP(404) headers = self.headers headers['Content-Type'] = contenttype(name) if download_filename == None: download_filename = filename if attachment: headers['Content-Disposition'] = \ 'attachment; filename="%s"' % download_filename.replace('"','\"') return self.stream(stream, chunk_size=chunk_size, request=request)
def stream( self, stream, chunk_size=DEFAULT_CHUNK_SIZE, request=None, ): """ if a controller function:: return response.stream(file, 100) the file content will be streamed at 100 bytes at the time """ if isinstance(stream, (str, unicode)): stream_file_or_304_or_206(stream, chunk_size=chunk_size, request=request, headers=self.headers) # ## the following is for backward compatibility if hasattr(stream, 'name'): filename = stream.name else: filename = None keys = [item.lower() for item in self.headers] if filename and not 'content-type' in keys: self.headers['Content-Type'] = contenttype(filename) if filename and not 'content-length' in keys: try: self.headers['Content-Length'] = \ os.path.getsize(filename) except OSError: pass if request and request.env.web2py_use_wsgi_file_wrapper: wrapped = request.env.wsgi_file_wrapper(stream, chunk_size) else: wrapped = streamer(stream, chunk_size=chunk_size) return wrapped
def download(): """ allow user to download files by name """ import contenttype as c if not request.args: raise HTTP(404) elif 'cms_file.cms_file' in request.args[-1]: return response.download(request, db) else: file_id = request.args[-1] for row in db(db.cms_file.id>0).select(): # search for the original filename if file_id in db.cms_file.cms_file.retrieve(row.cms_file): try: filename, file = db.cms_file.cms_file.retrieve(row.cms_file) except IOError: raise HTTP(404) response.headers["Content-Type"] = c.contenttype(file_id) response.headers["Content-Disposition"] = "attachment; filename=%s" % file_id stream = response.stream(file, chunk_size=64*1024, request=request) raise HTTP(200, stream, **response.headers)
def my_download(request, db, download_filename): """This implements my download procedure that can rename files.""" if not request.args: raise HTTP(404) name = request.args[-1] items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*')\ .match(name) if not items: raise HTTP(404) (t, f) = (items.group('table'), items.group('field')) try: field = db[t][f] except AttributeError: raise HTTP(404) try: (filename, stream) = field.retrieve(name) except IOError: raise HTTP(404) headers = response.headers headers['Content-Type'] = contenttype(name) headers['Content-Disposition'] = \ 'attachment; filename="%s"' % download_filename.replace('"','\"') return response.stream(stream, chunk_size=DEFAULT_CHUNK_SIZE)
def my_download(download_filename, subm_content=request.args[-1]): """This implements my download procedure that can rename files.""" if download_filename is None: download_filename = 'submission' name = subm_content items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*')\ .match(name) if not items: raise HTTP(404) (t, f) = (items.group('table'), items.group('field')) try: field = db[t][f] except AttributeError: raise HTTP(404) try: (filename, stream) = field.retrieve(name) except IOError: raise HTTP(404) headers = response.headers headers['Content-Type'] = contenttype(name) headers['Content-Disposition'] = \ 'attachment; filename="%s"' % download_filename.replace('"','\"') return response.stream(stream, chunk_size=DEFAULT_CHUNK_SIZE)
def stream_file_or_304_or_206(static_file, chunk_size=10 ** 6, request=None, headers={}, error_message=error_message): if not os.path.exists(static_file): raise HTTP(404, error_message, web2py_error="invalid file") stat_file = os.stat(static_file) fsize = stat_file[stat.ST_SIZE] mtime = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(stat_file[stat.ST_MTIME])) headers["Content-Type"] = contenttype(static_file) headers["Last-Modified"] = mtime headers["Pragma"] = "cache" headers["Cache-Control"] = "private" if request and request.env.http_if_modified_since == mtime: raise HTTP(304) elif request and request.env.http_range: start_items = regex_start_range.findall(request.env.http_range) if not start_items: start_items = [0] stop_items = regex_stop_range.findall(request.env.http_range) if not stop_items or int(stop_items[0]) > fsize - 1: stop_items = [fsize - 1] part = (int(start_items[0]), int(stop_items[0]), fsize) bytes = part[1] - part[0] + 1 try: stream = open(static_file, "rb") except IOError: raise HTTP(404) stream.seek(part[0]) headers["Content-Range"] = "bytes %i-%i/%i" % part headers["Content-Length"] = "%i" % bytes raise HTTP(206, streamer(stream, chunk_size=chunk_size, bytes=bytes), **headers) else: try: stream = open(static_file, "rb") except IOError: raise HTTP(404) headers["Content-Length"] = fsize raise HTTP(200, streamer(stream, chunk_size=chunk_size), **headers)
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, environ) = url_in(request, environ) if static_file: if environ.get("QUERY_STRING", "").startswith("attachment"): response.headers["Content-Disposition"] = "attachment" response.stream(static_file, request=request) # ################################################## # fill in request items # ################################################## app = request.application ## must go after url_in! http_host = 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 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", "HTTPS"] or env.https == "on", ) request.uuid = 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) # ################################################## # set no-cache headers # ################################################## headers = response.headers headers["Content-Type"] = contenttype("." + request.extension) headers["Cache-Control"] = "no-store, no-cache, must-revalidate, post-check=0, pre-check=0" headers["Expires"] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()) headers["Pragma"] = "no-cache" # ################################################## # 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_on_disk(request, response) # ################################################## # store cookies in headers # ################################################## if request.cid: rheaders = http_response.headers if response.flash and not "web2py-component-flash" in rheaders: rheaders["web2py-component-flash"] = urllib2.quote(xmlescape(response.flash).replace("\n", "")) if response.js and not "web2py-component-command" in rheaders: rheaders["web2py-component-command"] = response.js.replace("\n", "") rcookies = response.cookies if session._forget and response.session_id_name in response.cookies: 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 )
def stream(self, stream, chunk_size=DEFAULT_CHUNK_SIZE, request=None, attachment=False, filename=None): """ if a controller function:: return response.stream(file, 100) the file content will be streamed at 100 bytes at the time Optional kwargs: (for custom stream calls) attachment=True # Send as attachment. Usually creates a # pop-up download window on browsers filename=None # The name for the attachment Note: for using the stream name (filename) with attachments the option must be explicitly set as function parameter(will default to the last request argument otherwise) """ headers = self.headers # for attachment settings and backward compatibility keys = [item.lower() for item in headers] if attachment: if filename is None: attname = "" else: attname = filename headers["Content-Disposition"] = \ "attachment;filename=%s" % attname if not request: request = current.request if isinstance(stream, (str, unicode)): stream_file_or_304_or_206(stream, chunk_size=chunk_size, request=request, headers=headers, status=self.status) # ## the following is for backward compatibility if hasattr(stream, 'name'): filename = stream.name if filename and not 'content-type' in keys: headers['Content-Type'] = contenttype(filename) if filename and not 'content-length' in keys: try: headers['Content-Length'] = \ os.path.getsize(filename) except OSError: pass env = request.env # Internet Explorer < 9.0 will not allow downloads over SSL unless caching is enabled if request.is_https and isinstance(env.http_user_agent, str) and \ not re.search(r'Opera', env.http_user_agent) and \ re.search(r'MSIE [5-8][^0-9]', env.http_user_agent): headers['Pragma'] = 'cache' headers['Cache-Control'] = 'private' if request and env.web2py_use_wsgi_file_wrapper: wrapped = env.wsgi_file_wrapper(stream, chunk_size) else: wrapped = streamer(stream, chunk_size=chunk_size) return wrapped
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)
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 '/' """ rewrite.select(environ) if rewrite.thread.routes.routes_in: environ = rewrite.filter_in(environ) request = Request() response = Response() session = Session() static_file = False try: try: try: # ################################################## # parse the environment variables # ################################################## for (key, value) in environ.items(): request.env[key.lower().replace('.', '_')] = value request.env.web2py_path = web2py_path request.env.web2py_version = web2py_version request.env.update(settings) # ################################################## # invoke the legacy URL parser and serve static file # ################################################## static_file = parse_url(request, environ) if static_file: if request.env.get('query_string', '')[:10] == 'attachment': response.headers['Content-Disposition'] = 'attachment' response.stream(static_file, request=request) # ################################################## # build missing folder # ################################################## if not request.env.web2py_runtime_gae: for subfolder in [ 'models', 'views', 'controllers', 'databases', 'modules', 'cron', 'errors', 'sessions', 'languages', 'static', 'private', 'uploads' ]: path = os.path.join(request.folder, subfolder) if not os.path.exists(path): os.mkdir(path) # ################################################## # 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._custom_commit: response._custom_commit() else: BaseAdapter.close_all_instances(BaseAdapter.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'] = \ str(response.js).replace('\n','') if session._forget: 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(BaseAdapter.rollback) http_response = \ HTTP(500, rewrite.thread.routes.error_message_ticket % dict(ticket=ticket), web2py_error='ticket %s' % ticket)
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 '/' """ if rewrite.params.routes_in: environ = rewrite.filter_in(environ) request = Request() response = Response() session = Session() try: try: # ################################################## # parse the environment variables # ################################################## for (key, value) in environ.items(): request.env[key.lower().replace('.', '_')] = value request.env.web2py_path = web2py_path request.env.web2py_version = web2py_version request.env.update(settings) # ################################################## # validate the path in url # ################################################## if not request.env.path_info and request.env.request_uri: # for fcgi, decode path_info and query_string items = request.env.request_uri.split('?') request.env.path_info = items[0] if len(items) > 1: request.env.query_string = items[1] else: request.env.query_string = '' path = request.env.path_info.replace('\\', '/') # ################################################## # serve if a static file # ################################################## match = regex_static.match(regex_space.sub('_', path)) if match and match.group('x'): static_file = os.path.join(request.env.web2py_path, 'applications', match.group('b'), 'static', match.group('x')) if request.env.get('query_string', '')[:10] == 'attachment': response.headers['Content-Disposition'] = 'attachment' response.stream(static_file, request=request) # ################################################## # parse application, controller and function # ################################################## path = re.sub('%20', ' ', path) match = regex_url.match(path) if not match or match.group('c') == 'static': raise HTTP(400, rewrite.params.error_message, web2py_error='invalid path') request.application = \ regex_space.sub('_', match.group('a') or 'init') request.controller = \ regex_space.sub('_', match.group('c') or 'default') request.function = \ regex_space.sub('_', match.group('f') or 'index') group_e = match.group('e') raw_extension = group_e and regex_space.sub('_', group_e) or None request.extension = raw_extension or 'html' request.raw_args = match.group('r') request.args = List([]) if request.application in rewrite.params.routes_apps_raw: # application is responsible for parsing args request.args = None elif request.raw_args: match = regex_args.match(request.raw_args) if match: group_s = match.group('s') request.args = \ List((group_s and group_s.split('/')) or []) else: raise HTTP(400, rewrite.params.error_message, web2py_error='invalid path') request.client = get_client(request.env) request.folder = os.path.join(request.env.web2py_path, 'applications', request.application) + '/' # ################################################## # access the requested application # ################################################## if not os.path.exists(request.folder): if request.application == 'init': request.application = 'welcome' redirect(URL(r=request)) elif rewrite.params.error_handler: redirect( URL(rewrite.params.error_handler['application'], rewrite.params.error_handler['controller'], rewrite.params.error_handler['function'], args=request.application)) else: raise HTTP(400, rewrite.params.error_message, web2py_error='invalid application') request.url = URL(r=request, args=request.args, extension=raw_extension) # ################################################## # build missing folder # ################################################## if not request.env.web2py_runtime_gae: for subfolder in [ 'models', 'views', 'controllers', 'databases', 'modules', 'cron', 'errors', 'sessions', 'languages', 'static', 'private', 'uploads' ]: path = os.path.join(request.folder, subfolder) if not os.path.exists(path): os.mkdir(path) # ################################################## # 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 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._custom_commit: response._custom_commit() else: BaseAdapter.close_all_instances(BaseAdapter.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 session._forget: 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
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, environ) = url_in(request, environ) if static_file: if environ.get('QUERY_STRING','').startswith( 'attachment'): response.headers['Content-Disposition'] \ = 'attachment' response.stream(static_file, request=request) # ################################################## # fill in request items # ################################################## app = request.application ## must go after url_in! http_host = 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 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', 'HTTPS'] or env.https=='on') request.uuid = 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) # ################################################## # set no-cache headers # ################################################## headers = response.headers headers['Content-Type'] = \ contenttype('.'+request.extension) headers['Cache-Control'] = \ 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' headers['Expires'] = \ time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime()) headers['Pragma'] = 'no-cache' # ################################################## # 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_on_disk(request, response) # ################################################## # store cookies in headers # ################################################## if request.cid: rheaders = http_response.headers if response.flash and \ not 'web2py-component-flash' in rheaders: rheaders['web2py-component-flash'] = \ urllib2.quote(xmlescape(response.flash)\ .replace('\n','')) if response.js and \ not 'web2py-component-command' in rheaders: rheaders['web2py-component-command'] = \ response.js.replace('\n','') rcookies = response.cookies if session._forget and \ response.session_id_name in response.cookies: 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)
try: fp = open(static_file) except IOError, e: if e[0] == errno.EISDIR: raise HTTP(403, error_message, web2py_error='file is a directory') elif e[0] == errno.EACCES: raise HTTP(403, error_message, web2py_error='inaccessible file') else: raise HTTP(404, error_message, web2py_error='invalid file') else: fp.close() stat_file = os.stat(static_file) fsize = stat_file[stat.ST_SIZE] mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(stat_file[stat.ST_MTIME])) headers['Content-Type'] = contenttype(static_file) headers['Last-Modified'] = mtime headers['Pragma'] = 'cache' headers['Cache-Control'] = 'private' if request and request.env.http_if_modified_since == mtime: raise HTTP(304, **{'Content-Type': headers['Content-Type']}) elif request and request.env.http_range: start_items = regex_start_range.findall(request.env.http_range) if not start_items: start_items = [0] stop_items = regex_stop_range.findall(request.env.http_range) if not stop_items or int(stop_items[0]) > fsize - 1: stop_items = [fsize - 1] part = (int(start_items[0]), int(stop_items[0]), fsize)
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 '/' """ if rewrite.params.routes_in: environ = rewrite.filter_in(environ) request = Request() response = Response() session = Session() try: try: # ################################################## # parse the environment variables # ################################################## for (key, value) in environ.items(): request.env[key.lower().replace('.', '_')] = value request.env.web2py_path = web2py_path request.env.web2py_version = web2py_version request.env.update(settings) # ################################################## # validate the path in url # ################################################## if not request.env.path_info and request.env.request_uri: # for fcgi, decode path_info and query_string items = request.env.request_uri.split('?') request.env.path_info = items[0] if len(items) > 1: request.env.query_string = items[1] else: request.env.query_string = '' path = request.env.path_info.replace('\\', '/') path = regex_space.sub('_', path) match = regex_url.match(path) if not match: raise HTTP(400, rewrite.params.error_message, web2py_error='invalid path') # ################################################## # serve if a static file # ################################################## if match.group('c') == 'static': raise HTTP(400, rewrite.params.error_message) if match.group('x'): static_file = os.path.join(request.env.web2py_path, 'applications', match.group('b'), 'static', match.group('x')) if request.env.get('query_string', '')[:10] == 'attachment': response.headers['Content-Disposition'] = 'attachment' response.stream(static_file, request=request) # ################################################## # parse application, controller and function # ################################################## request.application = match.group('a') or 'init' request.controller = match.group('c') or 'default' request.function = match.group('f') or 'index' raw_extension = match.group('e') request.extension = raw_extension or 'html' request.args = \ List((match.group('s') and match.group('s').split('/')) or []) request.client = get_client(request.env) request.folder = os.path.join(request.env.web2py_path, 'applications', request.application) + '/' # ################################################## # access the requested application # ################################################## if not os.path.exists(request.folder): if request.application=='init': request.application = 'welcome' redirect(URL(r=request)) elif rewrite.params.error_handler: redirect(URL(rewrite.params.error_handler['application'], rewrite.params.error_handler['controller'], rewrite.params.error_handler['function'], args=request.application)) else: raise HTTP(400, rewrite.params.error_message, web2py_error='invalid application') request.url = URL(r=request,args=request.args, extension=raw_extension) # ################################################## # build missing folder # ################################################## if not request.env.web2py_runtime_gae: for subfolder in ['models','views','controllers', 'modules','cron','errors','sessions', 'languages','static','private','uploads']: path = os.path.join(request.folder,subfolder) if not os.path.exists(path): os.mkdir(path) # ################################################## # 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 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._custom_commit: response._custom_commit() else: BaseAdapter.close_all_instances(BaseAdapter.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 session._secure: response.cookies[response.session_id_name]['secure'] = \ True http_response.headers['Set-Cookie'] = [str(cookie)[11:] for cookie in response.cookies.values()] ticket=None
try: fp = open(static_file) except IOError, e: if e[0] == errno.EISDIR: raise HTTP(403, error_message, web2py_error="file is a directory") elif e[0] == errno.EACCES: raise HTTP(403, error_message, web2py_error="inaccessible file") else: raise HTTP(404, error_message, web2py_error="invalid file") else: fp.close() stat_file = os.stat(static_file) fsize = stat_file[stat.ST_SIZE] modified = stat_file[stat.ST_MTIME] mtime = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(modified)) headers.setdefault("Content-Type", contenttype(static_file)) headers.setdefault("Last-Modified", mtime) headers.setdefault("Pragma", "cache") headers.setdefault("Cache-Control", "private") if request and request.env.http_if_modified_since == mtime: raise HTTP(304, **{"Content-Type": headers["Content-Type"]}) elif request and request.env.http_range: start_items = regex_start_range.findall(request.env.http_range) if not start_items: start_items = [0] stop_items = regex_stop_range.findall(request.env.http_range) if not stop_items or int(stop_items[0]) > fsize - 1: stop_items = [fsize - 1] part = (int(start_items[0]), int(stop_items[0]), fsize)
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 '/' """ 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'] = '' (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 # ################################################## request.client = get_client(request.env) request.folder = os.path.join(request.env.applications_parent, 'applications', request.application) + '/' request.ajax = str(request.env.http_x_requested_with).lower() == 'xmlhttprequest' request.cid = request.env.http_web2py_component_element # ################################################## # 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: redirect(Url(rewrite.thread.routes.error_handler['application'], rewrite.thread.routes.error_handler['controller'], rewrite.thread.routes.error_handler['function'], args=request.application)) else: raise HTTP(404, rewrite.thread.routes.error_message % 'invalid request', web2py_error='invalid application') 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._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'] = \ str(response.js).replace('\n','') if session._forget: 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)
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 '/' """ rewrite.select(environ) if rewrite.params.routes_in: environ = rewrite.filter_in(environ) request = Request() response = Response() session = Session() static_file = False try: try: # ################################################## # parse the environment variables # ################################################## for (key, value) in environ.items(): request.env[key.lower().replace('.', '_')] = value request.env.web2py_path = web2py_path request.env.web2py_version = web2py_version request.env.update(settings) # ################################################## # invoke the legacy URL parser and serve static file # ################################################## static_file = parse_url(request, environ) if static_file: if request.env.get('query_string', '')[:10] == 'attachment': response.headers['Content-Disposition'] = 'attachment' response.stream(static_file, request=request) # ################################################## # build missing folder # ################################################## if not request.env.web2py_runtime_gae: for subfolder in ['models','views','controllers', 'databases', 'modules','cron','errors','sessions', 'languages','static','private','uploads']: path = os.path.join(request.folder,subfolder) if not os.path.exists(path): os.mkdir(path) # ################################################## # 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._custom_commit: response._custom_commit() else: BaseAdapter.close_all_instances(BaseAdapter.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'] = \ str(response.js).replace('\n','') if session._forget: 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
try: fp = open(static_file) except IOError, e: if e[0] == errno.EISDIR: raise HTTP(403, error_message, web2py_error='file is a directory') elif e[0] == errno.EACCES: raise HTTP(403, error_message, web2py_error='inaccessible file') else: raise HTTP(404, error_message, web2py_error='invalid file') else: fp.close() stat_file = os.stat(static_file) fsize = stat_file[stat.ST_SIZE] mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(stat_file[stat.ST_MTIME])) headers['Content-Type'] = contenttype(static_file) headers['Last-Modified'] = mtime headers['Pragma'] = 'cache' headers['Cache-Control'] = 'private' if request and request.env.http_if_modified_since == mtime: raise HTTP(304) elif request and request.env.http_range: start_items = regex_start_range.findall(request.env.http_range) if not start_items: start_items = [0] stop_items = regex_stop_range.findall(request.env.http_range) if not stop_items or int(stop_items[0]) > fsize - 1: stop_items = [fsize - 1] part = (int(start_items[0]), int(stop_items[0]), fsize) bytes = part[1] - part[0] + 1
try: fp = open(static_file) except IOError, e: if e[0] == errno.EISDIR: raise HTTP(403, error_message, web2py_error='file is a directory') elif e[0] == errno.EACCES: raise HTTP(403, error_message, web2py_error='inaccessible file') else: raise HTTP(404, error_message, web2py_error='invalid file') else: fp.close() stat_file = os.stat(static_file) fsize = stat_file[stat.ST_SIZE] modified = stat_file[stat.ST_MTIME] mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(modified)) headers.setdefault('Content-Type', contenttype(static_file)) headers.setdefault('Last-Modified', mtime) headers.setdefault('Pragma', 'cache') headers.setdefault('Cache-Control', 'private') # if this is a normal response and not a respnse to an error page if status == 200: if request and request.env.http_if_modified_since == mtime: raise HTTP(304, **{'Content-Type': headers['Content-Type']}) elif request and request.env.http_range: start_items = regex_start_range.findall(request.env.http_range) if not start_items: start_items = [0] stop_items = regex_stop_range.findall(request.env.http_range) if not stop_items or int(stop_items[0]) > fsize - 1:
def create_portable_app(web2py_source, copy_database=False, copy_uploads=False): """Function to create the portable app based on the parameters""" from gluon.admin import apath import shutil,tempfile,os import zipfile import contenttype cachedir = os.path.join(apath("%s" % appname, r=request), "cache") tempdir = tempfile.mkdtemp("", "eden-", cachedir) workdir = os.path.join(tempdir, "web2py") if copy_uploads: ignore = shutil.ignore_patterns("*.db", "*.log", "*.table", "errors", "sessions", "compiled" , "cache", ".bzr", "*.pyc") else: ignore = shutil.ignore_patterns("*.db", "*.log", "*.table", "errors", "sessions", "compiled" , "uploads", "cache", ".bzr", "*.pyc") appdir = os.path.join(workdir, "applications", appname) shutil.copytree(apath("%s" % appname, r=request),\ appdir, \ ignore = ignore) os.mkdir(os.path.join(appdir, "errors")) os.mkdir(os.path.join(appdir, "sessions")) os.mkdir(os.path.join(appdir, "cache")) if not copy_uploads: os.mkdir(os.path.join(appdir, "uploads")) shutil.copy(os.path.join(appdir, "deployment-templates", "cron", "crontab"),\ os.path.join(appdir, "cron", "crontab")) if copy_database: # Copy the db for the portable app s3db.load_all_models() # Load all modules to copy everything portable_db = DAL("sqlite://storage.db", folder=os.path.join(appdir, "databases")) for table in db: portable_db.define_table(table._tablename, *[field for field in table]) portable_db.commit() temp_csv_file=tempfile.mkstemp() db.export_to_csv_file(open(temp_csv_file[1], "wb")) portable_db.import_from_csv_file(open(temp_csv_file[1], "rb")) os.unlink(temp_csv_file[1]) portable_db.commit() # Replace the following with a more specific config config_template = open(os.path.join(appdir, "deployment-templates", "models", "000_config.py"), "r") new_config = open(os.path.join(appdir, "models", "000_config.py"), "w") # Replace first occurance of False with True new_config.write(config_template.read().replace("False", "True", 1)) new_config.close() # Embedded the web2py source with eden for download shutil.copy(os.path.join(cachedir, web2py_source), os.path.join(cachedir, "download.zip")) portable_app = os.path.join(cachedir, "download.zip") zip = zipfile.ZipFile(portable_app, "a", zipfile.ZIP_DEFLATED) tozip = os.path.join(tempdir, "web2py") rootlen = len(tempdir) + 1 for base, dirs, files in os.walk(tozip): for directory in dirs: directory = os.path.join(base, directory) zip.write(directory, directory[rootlen:]) # Create empty directories for file in files: fn = os.path.join(base, file) zip.write(fn, fn[rootlen:]) zip.close() shutil.rmtree(tempdir) response.headers["Content-Type"] = contenttype.contenttype(portable_app) response.headers["Content-Disposition"] = \ "attachment; filename=portable-sahana.zip" return response.stream(portable_app)
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)
def create_portable_app(web2py_source, copy_database=False, copy_uploads=False): """Function to create the portable app based on the parameters""" from gluon.admin import apath import shutil, tempfile, os import zipfile import contenttype cachedir = os.path.join(apath("%s" % appname, r=request), "cache") tempdir = tempfile.mkdtemp("", "eden-", cachedir) workdir = os.path.join(tempdir, "web2py") if copy_uploads: ignore = shutil.ignore_patterns("*.db", "*.log", "*.table", "errors", "sessions", "compiled", "cache", ".bzr", "*.pyc") else: ignore = shutil.ignore_patterns("*.db", "*.log", "*.table", "errors", "sessions", "compiled", "uploads", "cache", ".bzr", "*.pyc") appdir = os.path.join(workdir, "applications", appname) shutil.copytree(apath("%s" % appname, r=request),\ appdir, \ ignore = ignore) os.mkdir(os.path.join(appdir, "errors")) os.mkdir(os.path.join(appdir, "sessions")) os.mkdir(os.path.join(appdir, "cache")) if not copy_uploads: os.mkdir(os.path.join(appdir, "uploads")) shutil.copy(os.path.join(appdir, "deployment-templates", "cron", "crontab"),\ os.path.join(appdir, "cron", "crontab")) if copy_database: # Copy the db for the portable app s3db.load_all_models() # Load all modules to copy everything portable_db = DAL("sqlite://storage.db", folder=os.path.join(appdir, "databases")) for table in db: portable_db.define_table(table._tablename, *[field for field in table]) portable_db.commit() temp_csv_file = tempfile.mkstemp() db.export_to_csv_file(open(temp_csv_file[1], "wb")) portable_db.import_from_csv_file(open(temp_csv_file[1], "rb")) os.unlink(temp_csv_file[1]) portable_db.commit() # Replace the following with a more specific config config_template = open( os.path.join(appdir, "deployment-templates", "models", "000_config.py"), "r") new_config = open(os.path.join(appdir, "models", "000_config.py"), "w") # Replace first occurance of False with True new_config.write(config_template.read().replace("False", "True", 1)) new_config.close() # Embedded the web2py source with eden for download shutil.copy(os.path.join(cachedir, web2py_source), os.path.join(cachedir, "download.zip")) portable_app = os.path.join(cachedir, "download.zip") zip = zipfile.ZipFile(portable_app, "a", zipfile.ZIP_DEFLATED) tozip = os.path.join(tempdir, "web2py") rootlen = len(tempdir) + 1 for base, dirs, files in os.walk(tozip): for directory in dirs: directory = os.path.join(base, directory) zip.write(directory, directory[rootlen:]) # Create empty directories for file in files: fn = os.path.join(base, file) zip.write(fn, fn[rootlen:]) zip.close() shutil.rmtree(tempdir) response.headers["Content-Type"] = contenttype.contenttype(portable_app) response.headers["Content-Disposition"] = \ "attachment; filename=portable-sahana.zip" return response.stream(portable_app)
try: fp = open(static_file) except IOError, e: if e[0] == errno.EISDIR: raise HTTP(403, error_message, web2py_error='file is a directory') elif e[0] == errno.EACCES: raise HTTP(403, error_message, web2py_error='inaccessible file') else: raise HTTP(404, error_message, web2py_error='invalid file') else: fp.close() stat_file = os.stat(static_file) fsize = stat_file[stat.ST_SIZE] mtime = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(stat_file[stat.ST_MTIME])) headers.setdefault('Content-Type', contenttype(static_file)) headers.setdefault('Last-Modified', mtime) headers.setdefault('Pragma', 'cache') headers.setdefault('Cache-Control', 'private') if request and request.env.http_if_modified_since == mtime: raise HTTP(304, **{'Content-Type': headers['Content-Type']}) elif request and request.env.http_range: start_items = regex_start_range.findall(request.env.http_range) if not start_items: start_items = [0] stop_items = regex_stop_range.findall(request.env.http_range) if not stop_items or int(stop_items[0]) > fsize - 1: stop_items = [fsize - 1] part = (int(start_items[0]), int(stop_items[0]), fsize)