def __init__(self, config_file): self.__lang = None self.i18n = None self.direct_obj_ref = None self.cog_exec_env = None self.__env_set = False self.__nsession = False self._begin = None self.__cog_target = None self._cog_raw = None self._cog_ajax = None self._script_name = None self._server_name = None self._url_scheme = None self._environ = None self.__request = None self._session_key = None self.__session = None self._user = None self.__cog_environment = None self.__get_request = None self.cog_ref_obj = {} Controller.__init__(self, config_file) self.cache = Client(self) self.cache.check()
class WebController(Controller): """ Web controller. """ __static_body = None __topics = {} # topics are loaded on demand __site = None _d_topics = {} # all topics are loaded once! __main_topic = None def __init__(self, config_file): self.__lang = None self.i18n = None self.direct_obj_ref = None self.cog_exec_env = None self.__env_set = False self.__nsession = False self._begin = None self.__cog_target = None self._cog_raw = None self._cog_ajax = None self._script_name = None self._server_name = None self._url_scheme = None self._environ = None self.__request = None self._session_key = None self.__session = None self._user = None self.__cog_environment = None self.__get_request = None self.cog_ref_obj = {} Controller.__init__(self, config_file) self.cache = Client(self) self.cache.check() def clear(self): self.direct_obj_ref = None self.cog_exec_env = None self.__env_set = False self.__nsession = False self.__cog_target = None self._cog_raw = None self._cog_ajax = None self._environ = None self._user = None self.__request = None self._session_key = None self.__session = None self.__get_request = None self._json_res = {} self.cog_ref_obj = {} Controller.clear(self) @property def env_set(self): return self.__env_set def __rt(self, template_name): """ reads the templates and returns it's content """ params = self.db._cog_params tp = params['templates_path'] return open("%s/%s.html"%(tp, template_name)).read() def __get_tags(self): return self.db.table('collorg.communication.tag').search_links() def __get_important_posts(self): return self.db.table( 'collorg.communication.blog.view.by_post').important() @property def new_session(self): self.__nsession = True self._session_key = uuid.uuid4() return self._session_key def __get_static_body(self): self.db.table('collorg.core.base_table') dt = {} # templates dictionary params = self.db._cog_params html = self.__rt("html") dt['head'] = self.__rt("head") dt['title'] = self.db.name dt['style'] = self.__rt("style") dt['javascript'] = self.__rt("javascript") dt['head'] = dt['head'] % ( self._charset, dt['style'], params['icon'], dt['title'], dt['javascript']) dt['ariadne'] = self.__rt("ariadne") dt['top_search'] = self.__rt("top_search") dt['body'] = self.__rt("body") dt['header'] = self.__rt("header") dt['homepage_link'] = self.__rt("homepage_link") dt['homepage_link'] = "" #dt['homepage_link'] % (self._script_name) dt['search'] = self.__rt("search") dt['login_zone'] = self.__rt("login_zone") dt['header'] %= ( dt['homepage_link'], dt['login_zone']) dt['login_container'] = self.__rt("login_container") dt['body_content'] = self.__rt("body_content") dt['footer'] = self.__rt("footer") dt['collorg_link'] = self.__rt("collorg_link") dt['footer'] %= (dt['collorg_link']) dt['body'] %= ( dt['ariadne'], dt['top_search'], dt['header'], dt['login_container'], dt['body_content'], dt['footer']) dt['debug'] = self.__rt("debug") dt['collorg_link'] = self.__rt("collorg_link") html %= (dt['head'].decode(self._charset), dt['body'].decode(self._charset)) return html def __pfce(self, obj): return html_escape(str(pformat(obj))) def __oid_req(self, **kwargs): """ The controller received a cog_oid. The object representing one and only one elt of the table is instanciated. @returns: the method cog_method applied to this object. @called by: self.__exec """ if not '_cog_fqtn_' in self.__dict__ or not self._cog_fqtn_: obj = self.db.get_elt_by_oid(self._cog_oid_) else: obj = self.db.table(self._cog_fqtn_) obj.cog_oid_.value = self._cog_oid_ obj.get() self.check_action(obj, self._cog_method) self.cog_exec_env = obj.get_environment() if (self._user is None and obj._is_cog_post and obj.visibility_.value == 'public' and self._cog_method == 'w3display'): cache = obj._cog_get_cache('w3display') if cache is not None: return cache return eval("obj.{}(**kwargs)".format(self._cog_method)) def __fqtn_req(self, **kwargs): """ No cog_oid received by the controller but a cog_fqtn. @returns: the method referenced by cog_method applied to the object instantiated without intention (aka the whole table). @called by: self.__exec """ obj = self.db.table(self._cog_fqtn_) self.check_action(obj, self._cog_method) return eval("obj.{}(**kwargs)".format(self._cog_method)) def load_site(self): #XXX REFACTOR path_info = self._path_info if self.direct_obj_ref: path_info = '/' url = "{}{}".format( self._environ['HTTP_HOST'], self._environ.get('SCRIPT_NAME', '')) site = self.db.table("collorg.web.site") if not (url, path_info) in self.__topics: topic, w3display_topic = site.load_topic( url, path_info) if self.__site is None: self.__site = site.get() self.__topics[(url, path_info)] = (w3display_topic, topic) ### self._d_topics = self.__site.load_topics() topic = self.__topics[(url, path_info)][1] self._cog_cmd = self.__topics[(url, path_info)][0] return topic @property def site(self): return self.__site @property def main_topic(self): # Post._w3get_recipient if not self.__main_topic: self.__main_topic = self.__site.load_topic()[0] return self.__main_topic @property def _session(self): return self._session_key @property def user(self): return self._user @property def cog_environment(self): return self.__cog_environment def __dumps_json_res(self): res = {} for key, val in self._json_res.items(): res[key] = {'content':val, 'action':'html'} return json.dumps(res) def __get_query_params(self): qs = {} for query in self.__request.POST, self.__request.GET: for key, val in query.items(): key = key.encode(self._charset) val = val.encode(self._charset) if key[-2:] == '[]': key = key[:-2] if key not in qs: qs[key] = [] qs[key].append(val) else: qs[key] = val return qs def set_ref_obj_oid(self, obj_oid, ref_obj_oid): if obj_oid: self.cache.set_( "ref_obj_oid", self._session_key, (obj_oid, ref_obj_oid)) def set_env(self, env): if not self._session_key: return self.__env_set = True if self.__nsession: self.cache.set_("user", self._session_key, None) self.cache.set_( "creat_date", self._session_key, self._begin) self.cache.set_( "last_access_date", self._session_key, self._begin) def __get_env(self): if self._session_key: self.cache.get_("last_access_date", self._session_key) self.cache.set_( "last_access_date", self._session_key, self._begin) self.get_user() def get_user(self): if self._session_key: user_oid = self.cache.get_("user", self._session_key) if user_oid: self._user = self.db.table( 'collorg.actor.user', cog_oid_ = user_oid).get() else: self.delete_cookie('cog_session') def set_user(self, user_oid = None): self.cache.set_("user", self._session_key, user_oid) def del_user(self, key): self.cache.del_("user", key) def __get_params(self): self._kwargs = self.__get_query_params() self._cog_ajax = self._kwargs.get('cog_ajax') self.__cog_target = self._kwargs.get('cog_target') self._cog_raw = self._kwargs.get('cog_raw', None) self._cog_method = self._kwargs.get('cog_method', None) # cog_method must not contain non-word caracters assert self._cog_method is None or \ re.search('\W', self._cog_method) is None if self._cog_method is not None and self._cog_method[0] == '_': # we never should receive a protected method... self._cog_method = "w3error" self._kwargs['cog_method'] = "w3error" self._kwargs['cog_error'] = "Can't call a protected method!" self._cog_ref_oid = self._kwargs.get('cog_ref_oid', None) self._cog_oid_ = self._kwargs.get('cog_oid_', None) self._session_key = None if 'HTTP_COOKIE' in self._environ: cookie_string = self._environ.get('HTTP_COOKIE') cookie = SimpleCookie() cookie.load(cookie_string) if 'cog_session' in cookie: self._session_key = cookie['cog_session'].value self.__cog_environment = self.__get_env() self._cog_fqtn_ = self._kwargs.get('cog_fqtn_', None) if self._cog_ref_oid and self._cog_ref_oid == self._cog_oid_: self._cog_oid_ = None self._kwargs['cog_controller'] = self self._kwargs['cog_first_call'] = True def __reset(self): """ Some things that are always done first """ self._json_res['#cog_debug_link'] = '' self._json_res['#cog_debug'] = '' self.__get_params() self.db._set_controller(self) #self._cog_cmd = self.__environment def get_page_ref(self, method = None, oid = None): method = method or self._cog_method oid = oid or self._cog_oid_ if oid: ref = oid else: env = self._environ if env and 'QUERY_STRING' in env: ref = md5.new(env['QUERY_STRING']).hexdigest() else: ref = self.__site.cog_oid_.value page_ref = "{}-{}".format(method, ref) return page_ref def __exec(self): """ constructs the call to the template. the template receives depends on the arguments passed. Case of ajax: * one of the three following arguments is expected ** a path (specific wsgi) ** an oid ** a fqtn """ _ = self.i18n.gettext i18n_drag_drop = _( "Drag & drop your links here<br>for future reference") i18n_drop_drag = _( "Drag & drop the link from the cart to \n" "the page/textarea to add a reference.\n" "(write access is mandatory)") if self._cog_oid_: self._cog_cmd = self.__oid_req elif self._cog_fqtn_: self._cog_cmd = self.__fqtn_req elif self._cog_ajax is None and self.direct_obj_ref: self._cog_cmd = self.direct_obj_ref if self._cog_ajax is None: actor = self.db.table('collorg.actor.user') result = self.__static_body.format( self.__site.w3map_link(), _("search"), _("search"), _("by tag"), _("by user"), actor.w3login_link(), _(i18n_drop_drag).decode(self._charset), _(i18n_drag_drop).decode(self._charset)) page = self._cog_cmd(**self._kwargs) if self._cog_raw: return page result %= ( "", #self._json_res['#cog_top_nav_ariadne']), self._unicode(page)) return result # ajax try: result = self._cog_cmd(**self._kwargs) if self._cog_raw: return result duration = datetime.datetime.now() - self._begin except Exception as err: # open("/tmp/cog_error_log", "a+").write("{}\n".format(err)) if self.db._cog_params['debug']: link, error = self.debug(err.__str__) self._json_res['#cog_debug_link'] = link self._json_res['#cog_debug'] = self._unicode(error) return self.__dumps_json_res() if raise_error: raise "Web controller error: {}".format(err) self._json_res['#cog_duration'] = "%s" % (duration) if self._debug: link, debug = self.debug() self._json_res['#cog_debug_link'] = link self._json_res['#cog_debug'] = self._unicode(debug) self._json_res[self.__cog_target] = result return self.__dumps_json_res() def get_cookie(self, key): return self._session_key def delete_cookie(self, key): self.__response.delete_cookie(key) def set_cookie(self, key): value = self.new_session self.__response.set_cookie(key, bytes(value)) return value def process(self, environ, start_response): self._begin = datetime.datetime.now() if self._debug: open("/tmp/cog_sql", "w") try: self.clear() self._environ = environ # open("/tmp/cog_tmp_xxx", "w").write("{}".format(environ)) self._script_name = self._environ.get('SCRIPT_NAME', '') self._server_name = self._environ['HTTP_HOST'] self._url_scheme = self._environ['wsgi.url_scheme'] self._url = "{}://{}{}".format( self._url_scheme, self._server_name, self._script_name) self._path_info = self._environ['PATH_INFO'].lower() alnum = "[a-z0-9]{4}" oid_pattern = '^/{}{}-{}-{}-{}-{}{}{}$'.format(*(alnum,)*8) if re.match(oid_pattern, self._path_info): obj = self.db.get_elt_by_oid(self._path_info[1:]) self.add_json_res({'#page_ref':self.get_page_ref()}) self.direct_obj_ref = obj.w3display self.load_site() self.__request = Request(environ) self.__lang = Accept(str(self.__request.accept_language)) self.i18n = gettext.translation( 'messages', '/usr/share/collorg/locale', [self.__lang.best_match(('en', 'fr', 'fr-FR')) or 'en']) if WebController.__static_body is None: WebController.__tags = self.__get_tags() WebController.__static_body = self.__get_static_body() self.__response = Response() self.__reset() if not(self._cog_method is None and '#page_ref' in self._json_res): self.add_json_res({'#page_ref':self.get_page_ref()}) self.__response.unicode_body = self._unicode(self.__exec()) if(self.__response.content_type != 'text/html' or self.__response.status_int != 200): # Not an HTML response, we don't want to # do anything to it return self.__response(environ, start_response) # Make sure the content isn't gzipped: self.__response.decode_content() return self.__response(environ, start_response) except Exception as err: if self.db._cog_params['debug']: response = Response() response.unicode_body = self._unicode(err) return response(environ, start_response) if raise_error: raise err def debug(self, error = None): output = [] css_style = 'debug hidden toggle' css_error = '' if error: css_style += ' debug_error' css_error = 'debug_error' title = error and "Error" or "debug" link = ( '<span class="link toggle %s" ' 'to_toggle="#cog_debug">%s</span>' % (css_error, title)) if error: output.append('<h2>Error</h2>') output.append('<pre>%s</pre>' % (self.__pfce(error))) output.append("<h2>Traceback</h2>") output.append("<pre>%s</pre>"%( traceback.format_exc())) output.append('<h2>Main variables</h2>') output.append('<pre>') output.append('cog_method = %s\n' % (self._cog_method)) output.append('cog_fqtn_ = %s\n' % (self._cog_fqtn_)) output.append('cog_oid_ = %s\n' % (self._cog_oid_)) output.append('cog_ref_oid = %s\n' % (self._cog_ref_oid)) output.append('</pre>') if error: post_error = self.db.table( 'collorg.application.communication.error') try: post_error.hit( self._cog_fqtn_, self._cog_method, traceback.format_exc()) except Exception, err: sys.stderr.write("Warning! {}\n".format(err)) # open("/tmp/cog_error_log", "a+").write("{}\n".format(err)) output.append('<h2>Query string</h2>') output.append('<pre>qs = %s</pre>' % (self.__pfce(self.__get_request))) output.append('<h2>Command executed</h2>') output.append('<pre>cmd = %s</pre>' %(self.__pfce(self._cog_cmd))) output.append('<h2>Environ</h2>') output.append('<pre>%s</pre>' % (self.__pfce(self._environ))) u_output = [self._unicode(elt) for elt in output] return link, "\n".join(u_output)