def post_space_handler(environ, start_response): """ entry point for posting a new space name to TiddlyWeb """ space_name = environ['tiddlyweb.query']['name'][0] space = Space(environ) try: space.create_space(space_name, environ['tiddlyweb.config']['space']) except (RecipeExistsError, BagExistsError): raise HTTP409('Space already Exists: %s' % space_name) host = environ['tiddlyweb.config']['server_host'] if 'port' in host: port = ':%s' % host['port'] else: port = '' recipe = Recipe('%s_public' % space_name) new_space_uri = '%s/tiddlers.wiki' % recipe_url(environ, recipe) start_response('201 Created', [ ('Location', new_space_uri), ('Content-type', 'text/plain')]) return new_space_uri
def userpage(environ, start_response): username = environ['tiddlyweb.usersign']['name'] user = environ['wsgiorg.routing_args'][1]['user'] if username != user: #raise ForbiddenError raise UserRequiredError store = environ['tiddlyweb.store'] user_data = User(user) try: user_data = store.get(user_data) try: wikinames = user_data.note.split('\n') except AttributeError: wikinames = [] wikis = [] if wikinames: for name in wikinames: if not len(name): continue recipe = Recipe(name) recipe = store.get(recipe) url = recipe_url(environ, recipe) wikis.append(dict( name=name, url=url, description=recipe.desc)) except NoUserError: wikis = [] template = template_env.get_template('spowtuser.html') return template.generate(wikis=wikis)
def userpage(environ, start_response): username = environ['tiddlyweb.usersign']['name'] user = environ['wsgiorg.routing_args'][1]['user'] if username != user: #raise ForbiddenError raise UserRequiredError store = environ['tiddlyweb.store'] user_data = User(user) try: user_data = store.get(user_data) wikinames = user_data.note.split('\n') wikis = [] if wikinames: for name in wikinames: if not len(name): continue recipe = Recipe(name) recipe = store.get(recipe) url = recipe_url(environ, recipe) wikis.append(dict(name=name, url=url, description=recipe.desc)) except NoUserError: wikis = [] start_response('200 OK', [('Content-Type', 'text/html')]) environ['tiddlyweb.title'] = 'Hello %s' % user template = template_env.get_template('user.html') return template.generate(wikis=wikis)
def _recipe_policy(environ, recipe_name, publicity): user = get_user_object(environ) store = environ['tiddlyweb.store'] recipe = Recipe(recipe_name) recipe = store.get(recipe) recipe.policy.allows(user, 'manage') if publicity == 'custom': raise HTTP303(recipe_url(environ, recipe) + '/tiddlers') if publicity == 'public': recipe.policy.read = [] else: recipe.policy.read = [user['name']] store.put(recipe) raise HTTP303(recipe_url(environ, recipe) + '/tiddlers')
def _recipe_policy(environ, recipe_name, publicity): user = get_user_object(environ) store = environ['tiddlyweb.store'] recipe = Recipe(recipe_name) recipe = store.get(recipe) recipe.policy.allows(user, 'manage') if publicity == 'custom': raise HTTP303(recipe_url(environ, recipe) + '/tiddlers') if publicity == 'public': recipe.policy.read = [] else: recipe.policy.read = [user['name']] store.put(recipe) raise HTTP303(recipe_url(environ, recipe) + '/tiddlers')
def _recipe_policy(environ, recipe_name, publicity): user = get_user_object(environ) store = environ["tiddlyweb.store"] recipe = Recipe(recipe_name) recipe = store.get(recipe) recipe.policy.allows(user, "manage") if publicity == "custom": raise HTTP303(recipe_url(environ, recipe) + "/tiddlers") if publicity == "public": recipe.policy.read = [] else: recipe.policy.read = [user["name"]] store.put(recipe) raise HTTP303(recipe_url(environ, recipe) + "/tiddlers")
def get_tiddlers(environ, start_response): """ Handle ``GET`` on a tiddlers-within-a-recipe URI. Get a list representation of the :py:class:`tiddlers <tiddlyweb.model.tiddler.Tiddler>` generated from a :py:class:`recipe <tiddlyweb.model.recipe.Recipe>`. The information sent is dependent on the serialization chosen via :py:mod:`tiddlyweb.web.negotiate`. """ usersign = environ['tiddlyweb.usersign'] store = environ['tiddlyweb.store'] filters = environ['tiddlyweb.filters'] recipe = _determine_recipe(environ) title = 'Tiddlers From Recipe %s' % recipe.name title = environ['tiddlyweb.query'].get('title', [title])[0] # check the recipe can be read recipe.policy.allows(usersign, 'read') # check the bags in the recipe can be read try: template = control.recipe_template(environ) for bag_name, _ in recipe.get_recipe(template): bag = Bag(bag_name) bag = store.get(bag) bag.policy.allows(usersign, 'read') except NoBagError as exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc)) # from this point forward we know the tiddlers are # readable # get the tiddlers from the recipe and uniquify them try: candidate_tiddlers = control.get_tiddlers_from_recipe(recipe, environ) except NoBagError as exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc)) except FilterError as exc: raise HTTP400('malformed filter: %s' % exc) tiddlers = Tiddlers(title=title) if not filters: tiddlers.store = store tiddlers.recipe = recipe.name for tiddler in candidate_tiddlers: tiddler.recipe = recipe.name tiddlers.add(tiddler) tiddlers.link = '%s/tiddlers' % web.recipe_url(environ, recipe, full=False) return send_tiddlers(environ, start_response, tiddlers=tiddlers)
def get_tiddlers(environ, start_response): """ Handle ``GET`` on a tiddlers-within-a-recipe URI. Get a list representation of the :py:class:`tiddlers <tiddlyweb.model.tiddler.Tiddler>` generated from a :py:class:`recipe <tiddlyweb.model.recipe.Recipe>`. The information sent is dependent on the serialization chosen via :py:mod:`tiddlyweb.web.negotiate`. """ usersign = environ['tiddlyweb.usersign'] store = environ['tiddlyweb.store'] filters = environ['tiddlyweb.filters'] recipe = _determine_recipe(environ) title = 'Tiddlers From Recipe %s' % recipe.name title = environ['tiddlyweb.query'].get('title', [title])[0] # check the recipe can be read recipe.policy.allows(usersign, 'read') # check the bags in the recipe can be read try: template = control.recipe_template(environ) for bag_name, _ in recipe.get_recipe(template): bag = Bag(bag_name) bag = store.get(bag) bag.policy.allows(usersign, 'read') except NoBagError as exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc)) # from this point forward we know the tiddlers are # readable # get the tiddlers from the recipe and uniquify them try: candidate_tiddlers = control.get_tiddlers_from_recipe(recipe, environ) except NoBagError as exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc)) except FilterError as exc: raise HTTP400('malformed filter: %s' % exc) tiddlers = Tiddlers(title=title) if not filters: tiddlers.store = store tiddlers.recipe = recipe.name for tiddler in candidate_tiddlers: tiddler.recipe = recipe.name tiddlers.add(tiddler) tiddlers.link = '%s/tiddlers' % web.recipe_url(environ, recipe, full=False) return send_tiddlers(environ, start_response, tiddlers=tiddlers)
def put(environ, start_response): """ Handle ``PUT`` on a single recipe URI. Put a :py:class:`recipe <tiddlyweb.model.recipe.Recipe>` to the server, meaning the description, policy and recipe list of the recipe, if :py:class:`policy <tiddlyweb.model.policy.Policy>` allows. """ recipe_name = web.get_route_value(environ, 'recipe_name') recipe_name = web.handle_extension(environ, recipe_name) recipe = Recipe(recipe_name) store = environ['tiddlyweb.store'] length, _ = web.content_length_and_type(environ) usersign = environ['tiddlyweb.usersign'] try: recipe = store.get(recipe) recipe.policy.allows(usersign, 'manage') except NoRecipeError: create_policy_check(environ, 'recipe', usersign) try: serialize_type = web.get_serialize_type(environ)[0] except TypeError: raise HTTP400('Content-type header required') try: serializer = Serializer(serialize_type, environ) serializer.object = recipe content = web.read_request_body(environ, length) serializer.from_string(content.decode('utf-8')) recipe.policy.owner = usersign['name'] _validate_recipe(environ, recipe) store.put(recipe) except RecipeFormatError as exc: raise HTTP400('unable to put recipe: %s' % exc) except TypeError as exc: raise HTTP400('malformed input: %s' % exc) except NoSerializationError: raise HTTP415('Content type %s not supported' % serialize_type) start_response("204 No Content", [('Location', web.recipe_url(environ, recipe))]) return []
def put(environ, start_response): """ Handle ``PUT`` on a single recipe URI. Put a :py:class:`recipe <tiddlyweb.model.recipe.Recipe>` to the server, meaning the description, policy and recipe list of the recipe, if :py:class:`policy <tiddlyweb.model.policy.Policy>` allows. """ recipe_name = web.get_route_value(environ, 'recipe_name') recipe_name = web.handle_extension(environ, recipe_name) recipe = Recipe(recipe_name) store = environ['tiddlyweb.store'] length, _ = web.content_length_and_type(environ) usersign = environ['tiddlyweb.usersign'] try: recipe = store.get(recipe) recipe.policy.allows(usersign, 'manage') except NoRecipeError: create_policy_check(environ, 'recipe', usersign) try: serialize_type = web.get_serialize_type(environ)[0] except TypeError: raise HTTP400('Content-type header required') try: serializer = Serializer(serialize_type, environ) serializer.object = recipe content = web.read_request_body(environ, length) serializer.from_string(content.decode('utf-8')) recipe.policy.owner = usersign['name'] _validate_recipe(environ, recipe) store.put(recipe) except RecipeFormatError as exc: raise HTTP400('unable to put recipe: %s' % exc) except TypeError as exc: raise HTTP400('malformed input: %s' % exc) except NoSerializationError: raise HTTP415('Content type %s not supported' % serialize_type) start_response("204 No Content", [('Location', web.recipe_url(environ, recipe))]) return []
def _tiddlers_self(self, tiddler): """ Given a single tiddler from a collection determine the self URI of that collection. """ links = {} if tiddler.recipe: tiddlers_container = recipe_url(self.environ, Recipe(tiddler.recipe), full=True) links['tiddlyweb:recipe'] = tiddlers_container else: tiddlers_container = bag_url(self.environ, Bag(tiddler.bag), full=True) links['tiddlyweb:bag'] = tiddlers_container return links
def _tiddler_links(self, tiddler): """ The links to provide with a single tiddler. """ links = [] tiddler_link = tiddler_url(self.environ, tiddler, full=True) collection_link = self._tiddlers_links(Tiddlers(), tiddler)['self'] links.append(Link('tiddlyweb:tiddlers', collection_link)) links.append(Link('collection', collection_link)) links.append(Link('tiddlyweb:bag', bag_url(self.environ, Bag(tiddler.bag), full=True))) if tiddler.recipe: links.append(Link('tiddlyweb:recipe', recipe_url(self.environ, Recipe(tiddler.recipe), full=True))) links.append(Link('self', tiddler_link)) return links
def render(tiddler, environ, seen_titles=None): """ Return tiddler.text as rendered HTML by passing it down a socket to the nodejs based server.js process. Transclusions are identified in the returned text and processed recursively. If there is a current user, that user is passed along the pipe so that private content can be retrieved by nodejs (over HTTP). """ if seen_titles is None: seen_titles = [] parser = html5lib.HTMLParser( tree = html5lib.treebuilders.getTreeBuilder("dom")) if tiddler.recipe: collection = recipe_url(environ, Recipe(tiddler.recipe)) + '/tiddlers' else: collection = bag_url(environ, Bag(tiddler.bag)) + '/tiddlers' try: user_cookie = environ['HTTP_COOKIE'] cookie = Cookie.SimpleCookie() cookie.load(user_cookie) tiddlyweb_cookie = 'tiddlyweb_user='******'tiddlyweb_user'].value except KeyError: tiddlyweb_cookie = '' socket_path = environ['tiddlyweb.config'].get('twikified.socket', '/tmp/wst.sock') twik_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: twik_socket.connect(socket_path) except (socket.error, IOError), exc: output = """ <div class='error'>There was a problem rendering this tiddler. The raw text is given below.</div> <pre class='wikitext'>%s</pre> """ % (escape_attribute_value(tiddler.text)) logging.warn('twikifier socket connect failed: %s', exc) twik_socket.shutdown(socket.SHUT_RDWR) twik_socket.close() return output
def render(tiddler, environ, seen_titles=None): """ Return tiddler.text as rendered HTML by passing it down a socket to the nodejs based server.js process. Transclusions are identified in the returned text and processed recursively. If there is a current user, that user is passed along the pipe so that private content can be retrieved by nodejs (over HTTP). """ if seen_titles is None: seen_titles = [] parser = html5lib.HTMLParser( tree=html5lib.treebuilders.getTreeBuilder("dom")) if tiddler.recipe: collection = recipe_url(environ, Recipe(tiddler.recipe)) + '/tiddlers' else: collection = bag_url(environ, Bag(tiddler.bag)) + '/tiddlers' try: user_cookie = environ['HTTP_COOKIE'] cookie = Cookie.SimpleCookie() cookie.load(user_cookie) tiddlyweb_cookie = 'tiddlyweb_user='******'tiddlyweb_user'].value except KeyError: tiddlyweb_cookie = '' socket_path = environ['tiddlyweb.config'].get('twikified.socket', '/tmp/wst.sock') twik_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: twik_socket.connect(socket_path) except (socket.error, IOError), exc: output = """ <div class='error'>There was a problem rendering this tiddler. The raw text is given below.</div> <pre class='wikitext'>%s</pre> """ % (escape_attribute_value(tiddler.text)) logging.warn('twikifier socket connect failed: %s', exc) twik_socket.shutdown(socket.SHUT_RDWR) twik_socket.close() return output
def _tiddlers_collection_uri(self): """ Calculate the uri of the current tiddler collection. This ought to use tiddlyweb.model.collection but the code is not there yet. """ recipe_name = bag_name = None try: recipe_name = get_route_value(self.environ, 'recipe_name') except KeyError: try: bag_name = get_route_value(self.environ, 'bag_name') except KeyError: return None if recipe_name: base = recipe_url(self.environ, Recipe(recipe_name), full=True) else: base = bag_url(self.environ, Bag(bag_name), full=True) return base + '/tiddlers'
def render(tiddler, environ): if tiddler.recipe: collection = recipe_url(environ, Recipe(tiddler.recipe)) + '/tiddlers' else: collection = bag_url(environ, Bag(tiddler.bag)) + '/tiddlers' socket_path = environ['tiddlyweb.config'].get('twikified.socket', '/tmp/wst.sock') twik_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) twik_socket.connect('/tmp/wst.sock') twik_socket.sendall('%s\x00%s\n' % (collection, tiddler.title)) output = '' try: while True: data = twik_socket.recv(1024) if data: output += data else: break finally: twik_socket.close() return output.decode('UTF-8')
def render(tiddler, environ): if tiddler.recipe: collection = recipe_url(environ, Recipe(tiddler.recipe)) + '/tiddlers' else: collection = bag_url(environ, Bag(tiddler.bag)) + '/tiddlers' socket_path = environ['tiddlyweb.config'].get('twikified.socket', '/tmp/wst.sock') twik_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) twik_socket.connect('/tmp/wst.sock') twik_socket.sendall('%s\x00%s\n' % (collection, tiddler.title)) output = '' try: while True: data = twik_socket.recv(1024) if data: output += data else: break finally: twik_socket.close() return output.decode('UTF-8')
def put(environ, start_response): """ Put a new recipe to the server. """ recipe_name = environ["wsgiorg.routing_args"][1]["recipe_name"] recipe_name = urllib.unquote(recipe_name) recipe_name = unicode(recipe_name, "utf-8") recipe_name = web.handle_extension(environ, recipe_name) recipe = Recipe(recipe_name) store = environ["tiddlyweb.store"] length = environ["CONTENT_LENGTH"] usersign = environ["tiddlyweb.usersign"] try: recipe = store.get(recipe) recipe.policy.allows(usersign, "manage") except NoRecipeError: create_policy_check(environ, "recipe", usersign) try: serialize_type = web.get_serialize_type(environ)[0] serializer = Serializer(serialize_type, environ) serializer.object = recipe content = environ["wsgi.input"].read(int(length)) serializer.from_string(content.decode("utf-8")) recipe.policy.owner = usersign["name"] _validate_recipe(environ, recipe) store.put(recipe) except TypeError: raise HTTP400("Content-type header required") except NoSerializationError: raise HTTP415("Content type %s not supported" % serialize_type) start_response("204 No Content", [("Location", web.recipe_url(environ, recipe))]) return []
def render(tiddler, environ): if tiddler.recipe: collection = recipe_url(environ, Recipe(tiddler.recipe)) + '/tiddlers' else: collection = bag_url(environ, Bag(tiddler.bag)) + '/tiddlers' try: user_cookie = environ['HTTP_COOKIE'] cookie = Cookie.SimpleCookie() cookie.load(user_cookie) tiddlyweb_cookie = 'tiddlyweb_user='******'tiddlyweb_user'].value except KeyError: tiddlyweb_cookie = '' socket_path = environ['tiddlyweb.config'].get('twikified.socket', '/tmp/wst.sock') twik_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: twik_socket.connect('/tmp/wst.sock') except IOError: output = """ <div class='error'>There was a problem rendering this tiddler. The raw text is given instead below.</div> <pre class='wikitext'>%s</pre> """%(escape_attribute_value(tiddler.text)) return output twik_socket.sendall('%s\x00%s\x00%s\n' % (collection, tiddler.title, tiddlyweb_cookie)) output = '' try: while True: data = twik_socket.recv(1024) if data: output += data else: break finally: twik_socket.close() return output.decode('UTF-8')
def put(environ, start_response): """ Put a new recipe to the server. """ recipe_name = environ['wsgiorg.routing_args'][1]['recipe_name'] recipe_name = urllib.unquote(recipe_name) recipe_name = unicode(recipe_name, 'utf-8') recipe_name = web.handle_extension(environ, recipe_name) recipe = Recipe(recipe_name) store = environ['tiddlyweb.store'] length = environ['CONTENT_LENGTH'] usersign = environ['tiddlyweb.usersign'] try: recipe = store.get(recipe) recipe.policy.allows(usersign, 'manage') except NoRecipeError: create_policy_check(environ, 'recipe', usersign) try: serialize_type = web.get_serialize_type(environ)[0] serializer = Serializer(serialize_type, environ) serializer.object = recipe content = environ['wsgi.input'].read(int(length)) serializer.from_string(content.decode('UTF-8')) store.put(recipe) except NoSerializationError: raise HTTP415('Content type %s not supported' % serialize_type) start_response("204 No Content", [('Location', web.recipe_url(environ, recipe))]) return []
except NoBagError, exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc)) except FilterError, exc: raise HTTP400('malformed filter: %s' % exc) if filters: tiddlers = Tiddlers(title=title) else: tiddlers = Tiddlers(title=title, store=store) for tiddler in candidate_tiddlers: tiddler.recipe = recipe.name tiddlers.add(tiddler) tiddlers.link = '%s/tiddlers' % web.recipe_url(environ, recipe, full=False) return send_tiddlers(environ, start_response, tiddlers=tiddlers) def list_recipes(environ, start_response): """ Get a list of all recipes the current user can read. """ store = environ['tiddlyweb.store'] serialize_type, mime_type = web.get_serialize_type(environ) serializer = Serializer(serialize_type, environ) return list_entities(environ, start_response, mime_type, store.list_recipes, serializer.list_recipes)
def render(tiddler, environ): """ Return tiddler.text as rendered HTML by passing it down a socket to the nodejs based server.js process. Transclusions are identified in the returned text and processed recursively. If there is a current user, that user is passed along the pipe so that private content can be retrieved by nodejs (over HTTP). """ if tiddler.recipe: collection = recipe_url(environ, Recipe(tiddler.recipe)) + '/tiddlers' else: collection = bag_url(environ, Bag(tiddler.bag)) + '/tiddlers' try: user_cookie = environ['HTTP_COOKIE'] cookie = Cookie.SimpleCookie() cookie.load(user_cookie) tiddlyweb_cookie = 'tiddlyweb_user='******'tiddlyweb_user'].value except KeyError: tiddlyweb_cookie = '' socket_path = environ['tiddlyweb.config'].get('twikified.socket', '/var/run/twikifier/wst.sock') twik_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) twik_socket.settimeout(15.0) try: try: twik_socket.connect(socket_path) except (socket.error, IOError), exc: output = """ <div class='error'>There was a problem rendering this tiddler. The raw text is given below.</div> <pre class='wikitext'>%s</pre> """ % (escape_attribute_value(tiddler.text)) LOGGER.warn('twikifier socket connect failed: %s', exc) twik_socket.shutdown(socket.SHUT_RDWR) twik_socket.close() return output try: twik_socket.sendall('%s\x00%s\x00%s\n' % (collection, tiddler.text.encode('utf-8', 'replace'), tiddlyweb_cookie)) twik_socket.shutdown(socket.SHUT_WR) output = '' try: while True: data = twik_socket.recv(1024) if data: output += data else: break finally: twik_socket.shutdown(socket.SHUT_RDWR) twik_socket.close() except (socket.error, IOError), exc: if hasattr(exc, 'errno') and exc.errno == 57: twik_socket.close() else: LOGGER.warn('twikifier error during data processing: %s', exc) output = """ <div class='error'>There was a problem rendering this tiddler. The raw text is given below.</div> <pre class='wikitext'>%s</pre> """ % (escape_attribute_value(tiddler.text)) try: twik_socket.shutdown(socket.SHUT_RDWR) twik_socket.close() except (socket.error), exc: LOGGER.warn('twikifier bad socket shutdown: %s', exc) return output
def recipe_as(self, recipe): recipe_uri = recipe_url(self.environ, recipe, full=True) entity_structure = dict(policy=self._get_policy(recipe.policy), desc=recipe.desc, name=recipe.name, recipe=recipe.get_recipe()) return self._entity_as(entity_structure, recipe_uri, 'recipes')
content = environ['wsgi.input'].read(int(length)) serializer.from_string(content.decode('utf-8')) recipe.policy.owner = usersign['name'] _validate_recipe(environ, recipe) store.put(recipe) except RecipeFormatError, exc: raise HTTP400('unable to put recipe: %s' % exc) except TypeError, exc: raise HTTP400('malformed input: %s' % exc) except NoSerializationError: raise HTTP415('Content type %s not supported' % serialize_type) start_response("204 No Content", [('Location', web.recipe_url(environ, recipe))]) return [] def _validate_recipe(environ, recipe): """ Unless recipe is valid raise a 409 with the reason why. """ try: validate_recipe(recipe, environ) except InvalidBagError, exc: raise HTTP409('Recipe content is invalid: %s' % exc) def _determine_recipe(environ):
except NoBagError, exc: raise HTTP404('recipe %s lists an unknown bag: %s' % (recipe.name, exc)) except FilterError, exc: raise HTTP400('malformed filter: %s' % exc) if filters: tiddlers = Tiddlers(title=title) else: tiddlers = Tiddlers(title=title, store=store) for tiddler in candidate_tiddlers: tiddler.recipe = recipe.name tiddlers.add(tiddler) tiddlers.link = '%s/tiddlers' % web.recipe_url(environ, recipe, full=False) return send_tiddlers(environ, start_response, tiddlers=tiddlers) def list_recipes(environ, start_response): """ Get a list of all recipes the current user can read. """ store = environ['tiddlyweb.store'] serialize_type, mime_type = web.get_serialize_type(environ) serializer = Serializer(serialize_type, environ) return list_entities(environ, start_response, mime_type, store.list_recipes, serializer.list_recipes)
content = environ['wsgi.input'].read(int(length)) serializer.from_string(content.decode('utf-8')) recipe.policy.owner = usersign['name'] _validate_recipe(environ, recipe) store.put(recipe) except RecipeFormatError, exc: raise HTTP400('unable to put recipe: %s' % exc) except TypeError, exc: raise HTTP400('malformed input: %s' % exc) except NoSerializationError: raise HTTP415('Content type %s not supported' % serialize_type) start_response("204 No Content", [('Location', web.recipe_url(environ, recipe))]) return [] def _validate_recipe(environ, recipe): """ Unless recipe is valid raise a 409 with the reason why. """ try: validate_recipe(recipe, environ) except InvalidBagError, exc: raise HTTP409('Recipe content is invalid: %s' % exc) def _determine_recipe(environ):
def recipe_href(recipe, extension): return '%s/tiddlers%s?filter=%s' % ( recipe_url(environ, recipe), extension, urllib.quote('[sort[-modified]]') )
def render(tiddler, environ): """ Return tiddler.text as rendered HTML by passing it down a socket to the nodejs based server.js process. Transclusions are identified in the returned text and processed recursively. If there is a current user, that user is passed along the pipe so that private content can be retrieved by nodejs (over HTTP). """ if tiddler.recipe: collection = recipe_url(environ, Recipe(tiddler.recipe)) + '/tiddlers' else: collection = bag_url(environ, Bag(tiddler.bag)) + '/tiddlers' try: user_cookie = environ['HTTP_COOKIE'] cookie = Cookie.SimpleCookie() cookie.load(user_cookie) tiddlyweb_cookie = 'tiddlyweb_user='******'tiddlyweb_user'].value except KeyError: tiddlyweb_cookie = '' socket_path = environ['tiddlyweb.config'].get( 'twikified.socket', '/var/run/twikifier/wst.sock') twik_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) twik_socket.settimeout(15.0) try: try: twik_socket.connect(socket_path) except (socket.error, IOError), exc: output = """ <div class='error'>There was a problem rendering this tiddler. The raw text is given below.</div> <pre class='wikitext'>%s</pre> """ % (escape_attribute_value(tiddler.text)) LOGGER.warn('twikifier socket connect failed: %s', exc) twik_socket.shutdown(socket.SHUT_RDWR) twik_socket.close() return output try: twik_socket.sendall( '%s\x00%s\x00%s\n' % (collection, tiddler.text.encode('utf-8', 'replace'), tiddlyweb_cookie)) twik_socket.shutdown(socket.SHUT_WR) output = '' try: while True: data = twik_socket.recv(1024) if data: output += data else: break finally: twik_socket.shutdown(socket.SHUT_RDWR) twik_socket.close() except (socket.error, IOError), exc: if hasattr(exc, 'errno') and exc.errno == 57: twik_socket.close() else: LOGGER.warn('twikifier error during data processing: %s', exc) output = """ <div class='error'>There was a problem rendering this tiddler. The raw text is given below.</div> <pre class='wikitext'>%s</pre> """ % (escape_attribute_value(tiddler.text)) try: twik_socket.shutdown(socket.SHUT_RDWR) twik_socket.close() except (socket.error), exc: LOGGER.warn('twikifier bad socket shutdown: %s', exc) return output
def recipe_href(recipe, extension): return '%s/tiddlers%s?sort=-modified' % ( recipe_url(environ, recipe), extension)