def _status_gather_data(environ): """ Monkey patch twp.status to add additional information specific to TiddlySpace. """ data = original_gather_data(environ) data['server_host'] = environ['tiddlyweb.config']['server_host'] data['tiddlyspace_version'] = environ['tiddlyweb.config'][ 'tiddlyspace.version'] # gather space data http_host, host_url = determine_host(environ) if http_host != host_url: space_name = determine_space(environ, http_host) try: recipe_name = determine_space_recipe(environ, space_name) data['space'] = {'name': space_name, 'recipe': recipe_name} except HTTP404: pass # ensure user is known usersign = environ['tiddlyweb.usersign']['name'] store = environ['tiddlyweb.store'] try: store.get(User(usersign)) except NoUserError: data['username'] = '******' if usersign != 'GUEST': data['identity'] = usersign return data
def _valid_bag(self, environ, space, container_name): """ Return True if the requested entity is part of the current space's recipe or an ADMIN BAG. Otherwise return False indicating that privileges will be dropped. """ store = environ['tiddlyweb.store'] recipe_name = determine_space_recipe(environ, space.name) space_recipe = store.get(Recipe(recipe_name)) template = recipe_template(environ) recipe_bags = [bag for bag, _ in space_recipe.get_recipe(template)] recipe_bags.extend(space.extra_bags()) if environ['REQUEST_METHOD'] == 'GET': if container_name in recipe_bags: return True if container_name in ADMIN_BAGS: return True else: base_bags = space.list_bags() # add bags in the recipe which may have been added # by the recipe mgt. That is: bags which are not # included and not core. acceptable_bags = [bag for bag in recipe_bags if not ( Space.bag_is_public(bag) or Space.bag_is_private(bag) or Space.bag_is_associate(bag))] acceptable_bags.extend(base_bags) acceptable_bags.extend(ADMIN_BAGS) if container_name in acceptable_bags: return True return False
def safe_mode(environ, start_response): """ Serve up a space in safe mode. Safe mode means that non-required plugins are turned off and plugins that duplicate those in the core bags (system and tiddlyspace) are deleted from the store of the space in question. """ http_host, _ = determine_host(environ) space_name = determine_space(environ, http_host) recipe_name = determine_space_recipe(environ, space_name) if recipe_name != '%s_private' % space_name: raise HTTP403('membership required for safe mode') if environ['REQUEST_METHOD'] == 'GET': return _send_safe_mode(environ, start_response) store = environ['tiddlyweb.store'] # Get the list of core plugins core_plugin_tiddler_titles = _get_core_plugins(store) # Delete those plugins in the space's recipes which # duplicate the core plugins recipe = _delete_duplicates(environ, core_plugin_tiddler_titles, recipe_name, space_name) # Process the recipe. For those tiddlers which do not have a bag # in CORE_RECIPE, remove the systemConfig tag. try: candidate_tiddlers = control.get_tiddlers_from_recipe(recipe, environ) except NoBagError, exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc))
def _valid_bag(self, environ, space, container_name): """ Return True if the requested entity is part of the current space's recipe or an ADMIN BAG. Otherwise return False indicating that privileges will be dropped. """ store = environ['tiddlyweb.store'] recipe_name = determine_space_recipe(environ, space.name) space_recipe = store.get(Recipe(recipe_name)) template = recipe_template(environ) recipe_bags = [bag for bag, _ in space_recipe.get_recipe(template)] recipe_bags.extend(space.extra_bags()) if environ['REQUEST_METHOD'] == 'GET': if container_name in recipe_bags: return True if container_name in ADMIN_BAGS: return True else: base_bags = space.list_bags() # add bags in the recipe which may have been added # by the recipe mgt. That is: bags which are not # included and not core. acceptable_bags = [ bag for bag in recipe_bags if not (Space.bag_is_public(bag) or Space.bag_is_private(bag) or Space.bag_is_associate(bag)) ] acceptable_bags.extend(base_bags) acceptable_bags.extend(ADMIN_BAGS) if container_name in acceptable_bags: return True return False
def list_tiddlers(self, tiddlers): """ Override tiddlers.link so the location in noscript is to /tiddlers. """ http_host, _ = determine_host(self.environ) space_name = determine_space(self.environ, http_host) recipe_name = determine_space_recipe(self.environ, space_name) if '/recipes/%s' % recipe_name in tiddlers.link: tiddlers.link = '/tiddlers' return WikiSerialization.list_tiddlers(self, tiddlers)
def _handle_core_request(self, environ, req_uri, space_name, start_response): """ Override a core request, adding filters or sending 404s where necessary to limit the visibility of entities. """ recipe_name = determine_space_recipe(environ, space_name) store = environ['tiddlyweb.store'] try: recipe = store.get(Recipe(recipe_name)) except NoRecipeError, exc: raise HTTP404('No recipe for space: %s', exc)
def serve_space(environ, start_response, http_host): """ Serve a space determined from the current virtual host and user. The user determines whether the recipe uses is public or private. """ space_name = determine_space(environ, http_host) recipe_name = determine_space_recipe(environ, space_name) environ['wsgiorg.routing_args'][1]['recipe_name'] = recipe_name.encode( 'UTF-8') _, mime_type = get_serialize_type(environ) if 'text/html' in mime_type: environ['tiddlyweb.type'] = 'text/x-tiddlywiki' return get_tiddlers(environ, start_response)
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ if template_data == None: template_data = {} template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = { 'HtmlCss': ['/bags/common/tiddlers/profile.css'], 'HtmlJavascript': [] } # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe( recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: urls = tiddler.text.strip().rstrip().split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ if template_data == None: template_data = {} template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = { 'HtmlCss': ['/bags/common/tiddlers/profile.css'], 'HtmlJavascript': []} # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe(recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: urls = tiddler.text.strip().rstrip().split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def _setup_friendly_environ(environ): """ Manipulate the environ so that we appear to be in the context of the recipe appropriate for this current space and the current membership status. Return space_name to caller. """ http_host, host_url = determine_host(environ) if http_host == host_url: space_name = "frontpage" else: space_name = determine_space(environ, http_host) recipe_name = determine_space_recipe(environ, space_name) environ['wsgiorg.routing_args'][1]['recipe_name'] = recipe_name.encode( 'UTF-8')
def friendly_uri(environ, start_response): """ Transform a not alread mapped request at the root of a space into a request for a tiddler in the public or private recipe of the current space. """ http_host, host_url = determine_host(environ) if http_host == host_url: raise HTTP404('No resource found') else: space_name = determine_space(environ, http_host) recipe_name = determine_space_recipe(environ, space_name) # tiddler_name already in uri environ['wsgiorg.routing_args'][1]['recipe_name'] = recipe_name.encode( 'UTF-8') return get_tiddler(environ, start_response)
def _handle_dropping_privs(self, environ, req_uri): if environ['tiddlyweb.usersign']['name'] == 'GUEST': return http_host, _ = determine_host(environ) space_name = determine_space(environ, http_host) if space_name == None: return space = Space(space_name) store = environ['tiddlyweb.store'] container_name = req_uri.split('/')[2] if req_uri.startswith('/bags/'): recipe_name = determine_space_recipe(environ, space_name) space_recipe = store.get(Recipe(recipe_name)) template = recipe_template(environ) recipe_bags = [bag for bag, _ in space_recipe.get_recipe(template)] recipe_bags.extend(space.extra_bags()) if environ['REQUEST_METHOD'] == 'GET': if container_name in recipe_bags: return if container_name in ADMIN_BAGS: return else: base_bags = space.list_bags() # add bags in the recipe which may have been added # by the recipe mgt. That is: bags which are not # included and not core. acceptable_bags = [ bag for bag in recipe_bags if not (Space.bag_is_public(bag) or Space.bag_is_private( bag) or Space.bag_is_associate(bag)) ] acceptable_bags.extend(base_bags) acceptable_bags.extend(ADMIN_BAGS) if container_name in acceptable_bags: return if (req_uri.startswith('/recipes/') and container_name in space.list_recipes()): return self._drop_privs(environ) return
def _handle_dropping_privs(self, environ, req_uri): if environ['tiddlyweb.usersign']['name'] == 'GUEST': return http_host, _ = determine_host(environ) space_name = determine_space(environ, http_host) if space_name == None: return space = Space(space_name) store = environ['tiddlyweb.store'] container_name = req_uri.split('/')[2] if req_uri.startswith('/bags/'): recipe_name = determine_space_recipe(environ, space_name) space_recipe = store.get(Recipe(recipe_name)) template = recipe_template(environ) recipe_bags = [bag for bag, _ in space_recipe.get_recipe(template)] recipe_bags.extend(space.extra_bags()) if environ['REQUEST_METHOD'] == 'GET': if container_name in recipe_bags: return if container_name in ADMIN_BAGS: return else: base_bags = space.list_bags() # add bags in the recipe which may have been added # by the recipe mgt. That is: bags which are not # included and not core. acceptable_bags = [bag for bag in recipe_bags if not ( Space.bag_is_public(bag) or Space.bag_is_private(bag) or Space.bag_is_associate(bag))] acceptable_bags.extend(base_bags) acceptable_bags.extend(ADMIN_BAGS) if container_name in acceptable_bags: return if (req_uri.startswith('/recipes/') and container_name in space.list_recipes()): return self._drop_privs(environ) return
def validate_mapspace(tiddler, environ): """ If a tiddler is put to the MAPSPACE bag clear out the tiddler and set fields['mapped_space'] to the current space. Elsewhere in the space the mapped_space can map a alien domain to space. """ if tiddler.bag == 'MAPSPACE': current_space = determine_space(environ, determine_host(environ)[0]) recipe_name = determine_space_recipe(environ, current_space) if recipe_name != '%s_private' % current_space: raise InvalidTiddlerError('non member may not map space') tiddler.text = '' tiddler.tags = [] tiddler.fields = {} tiddler.fields['mapped_space'] = current_space return tiddler
def _handle_core_request(self, environ, req_uri): """ Override a core request, adding filters or sending 404s where necessary to limit the view of entities. filtering can be disabled with a custom HTTP header X-ControlView set to false """ http_host, host_url = determine_host(environ) request_method = environ['REQUEST_METHOD'] disable_ControlView = environ.get('HTTP_X_CONTROLVIEW') == 'false' if http_host != host_url and not disable_ControlView: space_name = determine_space(environ, http_host) if space_name == None: return recipe_name = determine_space_recipe(environ, space_name) store = environ['tiddlyweb.store'] try: recipe = store.get(Recipe(recipe_name)) except NoRecipeError, exc: raise HTTP404('No recipe for space: %s', exc) space = Space(space_name) template = recipe_template(environ) bags = space.extra_bags() for bag, _ in recipe.get_recipe(template): bags.append(bag) bags.extend(ADMIN_BAGS) filter_string = None if req_uri.startswith('/recipes') and req_uri.count('/') == 1: filter_string = 'oom=name:' if recipe_name == space.private_recipe(): filter_parts = space.list_recipes() else: filter_parts = [space.public_recipe()] filter_string += ','.join(filter_parts) elif req_uri.startswith('/bags') and req_uri.count('/') == 1: filter_string = 'oom=name:' filter_parts = bags filter_string += ','.join(filter_parts) elif req_uri.startswith('/search') and req_uri.count('/') == 1: filter_string = 'oom=bag:' filter_parts = bags filter_string += ','.join(filter_parts) else: entity_name = req_uri.split('/')[2] if '/recipes/' in req_uri: valid_recipes = space.list_recipes() if entity_name not in valid_recipes: raise HTTP404('recipe %s not found' % entity_name) else: if entity_name not in bags: raise HTTP404('bag %s not found' % entity_name) if filter_string: filters, _ = parse_for_filters(filter_string) for single_filter in filters: environ['tiddlyweb.filters'].insert(0, single_filter)
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ default_css_tiddler = '/bags/common/tiddlers/profile.css' if template_data is None: template_data = {} html_template_prefix = environ['tiddlyweb.space_settings']['htmltemplate'] if html_template_prefix: default_css_tiddler = ('/bags/common/tiddlers/%s.css' % html_template_prefix) html_template_prefix += '/' try: name = html_template_prefix + template_name template = get_template(environ, name) except TemplateNotFound: template = get_template(environ, template_name) else: template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = {'HtmlCss': [], 'HtmlJavascript': []} if not html_template_prefix or template_name in CUSTOMIZABLES: linked_resources['HtmlCss'] = [default_css_tiddler] # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe( recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: url_content = tiddler.text.strip() if url_content: urls = url_content.split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def _handle_core_request(self, environ, req_uri, start_response): """ Override a core request, adding filters or sending 404s where necessary to limit the view of entities. filtering can be disabled with a custom HTTP header X-ControlView set to false """ http_host, host_url = determine_host(environ) disable_ControlView = environ.get('HTTP_X_CONTROLVIEW') == 'false' if http_host != host_url and not disable_ControlView: space_name = determine_space(environ, http_host) if space_name == None: return None recipe_name = determine_space_recipe(environ, space_name) store = environ['tiddlyweb.store'] try: recipe = store.get(Recipe(recipe_name)) except NoRecipeError, exc: raise HTTP404('No recipe for space: %s', exc) space = Space(space_name) template = recipe_template(environ) bags = space.extra_bags() for bag, _ in recipe.get_recipe(template): bags.append(bag) bags.extend(ADMIN_BAGS) search_string = None if req_uri.startswith('/recipes') and req_uri.count('/') == 1: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) if recipe_name == space.private_recipe(): recipes = space.list_recipes() else: recipes = [space.public_recipe()] def lister(): for recipe in recipes: yield Recipe(recipe) return list_entities(environ, start_response, mime_type, lister, serializer.list_recipes) elif req_uri.startswith('/bags') and req_uri.count('/') == 1: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) def lister(): for bag in bags: yield Bag(bag) return list_entities(environ, start_response, mime_type, lister, serializer.list_bags) elif req_uri.startswith('/search') and req_uri.count('/') == 1: search_string = ' OR '.join(['bag:%s' % bag for bag in bags]) else: entity_name = urllib.unquote( req_uri.split('/')[2]).decode('utf-8') if '/recipes/' in req_uri: valid_recipes = space.list_recipes() if entity_name not in valid_recipes: raise HTTP404( 'recipe %s not found due to ControlView' % entity_name) else: if entity_name not in bags: raise HTTP404('bag %s not found due to ControlView' % entity_name) if search_string: search_query = environ['tiddlyweb.query'].get('q', [''])[0] environ['tiddlyweb.query.original'] = search_query if search_query: search_query = '%s AND (%s)' % (search_query, search_string) environ['tiddlyweb.query']['q'][0] = search_query else: search_query = '(%s)' % search_string environ['tiddlyweb.query']['q'] = [search_query]
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ default_css_tiddler = '/bags/common/tiddlers/profile.css' if template_data is None: template_data = {} html_template_prefix = environ['tiddlyweb.space_settings']['htmltemplate'] if html_template_prefix: default_css_tiddler = ('/bags/common/tiddlers/%s.css' % html_template_prefix) html_template_prefix += '/' try: name = html_template_prefix + template_name template = get_template(environ, name) except TemplateNotFound: template = get_template(environ, template_name) else: template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = { 'HtmlCss': [], 'HtmlJavascript': []} if not html_template_prefix or template_name in CUSTOMIZABLES: linked_resources['HtmlCss'] = [default_css_tiddler] # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe(recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: url_content = tiddler.text.strip() if url_content: urls = url_content.split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def _handle_core_request(self, environ, req_uri, start_response): """ Override a core request, adding filters or sending 404s where necessary to limit the view of entities. filtering can be disabled with a custom HTTP header X-ControlView set to false """ http_host, host_url = determine_host(environ) disable_ControlView = environ.get('HTTP_X_CONTROLVIEW') == 'false' if http_host != host_url and not disable_ControlView: space_name = determine_space(environ, http_host) if space_name == None: return None recipe_name = determine_space_recipe(environ, space_name) store = environ['tiddlyweb.store'] try: recipe = store.get(Recipe(recipe_name)) except NoRecipeError, exc: raise HTTP404('No recipe for space: %s', exc) space = Space(space_name) template = recipe_template(environ) bags = space.extra_bags() for bag, _ in recipe.get_recipe(template): bags.append(bag) bags.extend(ADMIN_BAGS) search_string = None if req_uri.startswith('/recipes') and req_uri.count('/') == 1: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) if recipe_name == space.private_recipe(): recipes = space.list_recipes() else: recipes = [space.public_recipe()] def lister(): for recipe in recipes: yield Recipe(recipe) return list_entities(environ, start_response, mime_type, lister, serializer.list_recipes) elif req_uri.startswith('/bags') and req_uri.count('/') == 1: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) def lister(): for bag in bags: yield Bag(bag) return list_entities(environ, start_response, mime_type, lister, serializer.list_bags) elif req_uri.startswith('/search') and req_uri.count('/') == 1: search_string = ' OR '.join(['bag:%s' % bag for bag in bags]) else: entity_name = urllib.unquote( req_uri.split('/')[2]).decode('utf-8') if '/recipes/' in req_uri: valid_recipes = space.list_recipes() if entity_name not in valid_recipes: raise HTTP404('recipe %s not found due to ControlView' % entity_name) else: if entity_name not in bags: raise HTTP404('bag %s not found due to ControlView' % entity_name) if search_string: search_query = environ['tiddlyweb.query'].get('q', [''])[0] environ['tiddlyweb.query.original'] = search_query if search_query: search_query = '%s AND (%s)' % (search_query, search_string) environ['tiddlyweb.query']['q'][0] = search_query else: search_query = '(%s)' % search_string environ['tiddlyweb.query']['q'] = [search_query]