from wsgicollection import Collection from config import config, log from model import model from robaccia import render, etag_from_raw_etag, http404, http304, http405, http415 import mcoll import os import cgi import re import sha import view.main from urlparse import urljoin, urlunparse import time from tempfile import mkstemp from mimetypes import guess_extension from subprocess import Popen, PIPE import shutil tz = "%+03d:00" % (-time.altzone/3600,) class AdminCollection(Collection): def __call__(self, environ, start_response): ctype = environ["wsgiorg.routing_args"][1]['ctype'] self.c = model.collection(ctype) self.ctype = ctype return super(type(self), self).__call__(environ, start_response) def list(self, environ, start_response): environ['1812.collection'] = self.ctype return view.main.list(environ, start_response) def retrieve(self, environ, start_response): environ['1812.collection'] = self.ctype return view.main.retrieve(environ, start_response) def main(environ, start_response): return render(environ, start_response, "admin_main.xhtml", {}) class Comments(Collection): def __init__(self, readonly=True): self.readonly = readonly def list(self, environ, start_response): ids = model.recent_comments('entry')[:config.getint("display", "entries_per_page")] comments = [] for (id, comment_id) in ids: member = model.comments('entry', id).get(comment_id) if member: member['entry_id'] = id member['entry'] = model.entry.get(id) comments.append(member) return render(environ, start_response, "comment_list.xhtml", {'comments': comments, 'readonly': self.readonly}) def delete(self, environ, start_response): if self.readonly: return http405(environ, start_response) id = environ["wsgiorg.routing_args"][1]['id'] (id, comment_id) = id.split("-") model.comments('entry', id).delete(comment_id) start_response("303 See Other", [('Location', urljoin(environ['REQUEST_URI'], "."))]) return [] # Atom Publishing Protocol def entry_from_feed(feed): entry = feed.entries[0] member = {} member['title'] = entry.title log.info(entry.title_detail) if 'summary_detail' in entry: member['summary'] = entry.summary_detail.value else: member['summary'] = "" member['content'] = entry.content[0].value return member class AppCollection(Collection): def __call__(self, environ, start_response): ctype = environ["wsgiorg.routing_args"][1].get('ctype', '') if ctype: self.c = model.collection(ctype) self.ctype = ctype self.ismedia = model.ismedia(ctype) return super(type(self), self).__call__(environ, start_response) def _mediafilename(self, id, slug, ext): return os.path.join(config.get(self.ctype, 'media_dir'), id + "-" + slug + ext) def _mediauri(self, id, slug, ext): return urljoin(config.get(self.ctype, 'media_uri'), id + "-" + slug + ext) def get_service_document(self, environ, start_response): entry, media = model.allcollections() return render(environ, start_response, "appservice.svc", {"entry": entry, "media": media }) # GET /drafts/ def list(self, environ, start_response): # page # pulled out from query parms # Add middleware to stuff a cgi.FieldStorage somewhere f = cgi.FieldStorage() page = 0 if f.has_key('page'): page = int(f["page"].value) ids = self.c.id_list_by_updated()[(page*20):((page+1)*20)] raw_etag = '"%s"' % sha.sha("".join(ids)).hexdigest() self_uri = "http://" + environ['SERVER_NAME'] + environ['REQUEST_URI'] next = 0 if self.c.id_list_by_updated()[(page+1*20):((page+2)*20)]: next = page + 1 if page and not ids: return http404(environ, start_response) entry_list = [self.c.get_by_updated_id(id) for id in ids] if entry_list: feedupdated = entry_list[0].updated else: feedupdated = "2006-01-01T12:00:00" return render(environ, start_response, "appfeed.atom", {"entry_list": entry_list, "ctype": self.ctype, "next": next, "self_uri": self_uri, "tz": tz, "feedupdated": feedupdated}, raw_etag = raw_etag) def _putmedia(self, environ): body = environ['wsgi.input'].read() (fd, filename) = mkstemp() file = os.fdopen(fd, 'w+b', -1) # write out the file into tmp file.write(body) file.close() if 'CONTENT_TYPE' not in environ: try: contenttype = Popen(["file", "-i", filename], stdout=PIPE).communicate()[0].split(":")[1].strip() except OSError: pass else: contenttype = environ['CONTENT_TYPE'] # Require the media-type ext = guess_extension(contenttype) summary = '' if contenttype.startswith('image'): imageinfo = Popen(["identify", "-verbose", filename], stdout=PIPE).communicate()[0] match = re.search("Comment:(.*)$", imageinfo, re.MULTILINE) if match: summary = match.groups()[0] return ext, contenttype, summary, filename # POST /drafts/ def create(self, environ, start_response): if self.ismedia: # Read and store the media. # Extract info from the image using 'identify' if appropriate # create the message, including the path to the newly created file ext, contenttype, summary, filename = self._putmedia(environ) if not contenttype: os.unlink(filename) return http415(environ, start_response, "