terom@197: from django.conf import settings terom@197: terom@197: import codecs terom@197: import logging; log = logging.getLogger('qmsk_www_pages.pages') terom@197: import os, os.path terom@197: terom@199: class Tree (object): terom@200: INDEX = 'index' terom@200: terom@199: @classmethod terom@199: def lookup (cls, parts): terom@199: path = settings.QMSK_WWW_PAGES_DIR terom@199: terom@199: for part in parts: terom@199: if part.startswith('.'): terom@199: # evil terom@199: return None terom@199: terom@199: if not part: terom@199: continue terom@199: terom@199: path = os.path.join(path, part) terom@199: terom@199: if not os.path.exists(path): terom@199: return None terom@199: terom@199: if not os.path.isdir(path): terom@199: return None terom@199: terom@199: return cls(path, parts) terom@199: terom@199: def __init__ (self, path, parts): terom@199: self.path = path terom@199: self.parts = parts terom@199: terom@200: terom@200: def url (self, tree=None, page=None): terom@200: path = '/'.join(self.parts) terom@200: terom@200: if path: terom@200: path += '/' terom@200: terom@200: if tree: terom@200: path = tree + '/' terom@200: terom@200: if page: terom@200: path += page terom@200: terom@200: return path terom@200: terom@201: def breadcrumb (self): terom@201: path = [] terom@201: terom@201: yield '', 'Home' terom@201: terom@201: for part in self.parts: terom@201: path.append(part) terom@201: terom@201: yield '/'.join(path) + '/', part terom@201: terom@200: def scan (self): terom@200: """ terom@200: Scan for files in tree. terom@200: """ terom@200: terom@200: for filename in os.listdir(self.path): terom@200: if filename.startswith('.'): terom@200: continue terom@200: terom@200: if '.' in filename: terom@200: file_name, file_type = filename.rsplit('.', 1) terom@200: else: terom@200: file_name = filename terom@200: file_type = None terom@200: terom@200: if not file_name: terom@200: continue terom@200: terom@200: path = os.path.join(self.path, filename) terom@200: terom@200: yield path, file_name, file_type terom@200: terom@200: def list (self): terom@200: """ terom@200: Lists all Trees and Pages for this Tree terom@200: """ terom@200: terom@200: for path, file_name, file_type in self.scan(): terom@200: # trees terom@200: if os.path.isdir(path): terom@200: yield self.url(tree=file_name), file_name terom@200: terom@200: if file_name == self.INDEX: terom@200: continue terom@200: terom@200: # pages terom@200: if not file_type: terom@200: continue terom@200: terom@200: if file_type not in TYPES: terom@200: continue terom@200: terom@200: yield self.url(page=file_name), file_name terom@200: terom@199: def page (self, name): terom@199: """ terom@199: Scans through tree looking for a matching page. terom@199: terom@199: Returns Page. terom@199: """ terom@200: terom@200: if not name: terom@200: name = self.INDEX terom@199: terom@200: for path, file_name, file_type in self.scan(): terom@200: # match on name terom@199: if file_name != name: terom@199: continue terom@199: terom@200: # match on type terom@200: if not file_type: terom@200: continue terom@200: terom@199: page_type = TYPES.get(file_type) terom@199: terom@199: if not page_type: terom@199: continue terom@200: terom@200: # out terom@199: return page_type( terom@199: path = path, terom@199: name = name, terom@199: tree = self, terom@199: ) terom@199: terom@197: class Page (object): terom@197: ENCODING = 'utf-8' terom@197: terom@197: @classmethod terom@197: def lookup (cls, page): terom@197: """ terom@197: Lookup a Page from disk. terom@197: terom@197: Returns None if there is no such page. terom@197: """ terom@197: terom@197: log.info("page=%r", page) terom@197: terom@197: if page: terom@197: parts = page.split('/') terom@197: else: terom@197: parts = [ ] terom@197: terom@197: if parts: terom@197: page_name = parts.pop(-1) terom@199: tree_parts = parts terom@197: else: terom@197: page_name = '' terom@199: tree_parts = [] terom@197: terom@197: # scan dir terom@199: tree = Tree.lookup(tree_parts) terom@197: terom@199: if not tree: terom@197: return None terom@197: terom@199: # scan page terom@199: page = tree.page(page_name) terom@197: terom@199: if not page: terom@199: return None terom@199: terom@199: return page terom@199: terom@199: def __init__ (self, path, name, tree, encoding=ENCODING): terom@197: self.path = path terom@197: self.name = name terom@199: self.tree = tree terom@197: self.encoding = encoding terom@197: terom@201: def url (self): terom@201: return self.tree.url(page=self.name) terom@201: terom@197: def open (self): terom@197: return codecs.open(self.path, encoding=self.encoding) terom@197: terom@198: def breadcrumb (self): terom@201: for path, name in self.tree.breadcrumb(): terom@201: yield path, name terom@200: terom@200: if self.name != self.tree.INDEX: terom@201: yield self.url(), self.name terom@198: terom@197: def render (self, request): terom@197: raise NotImplementedError() terom@197: terom@197: class HTML_Page (Page): terom@197: def render (self, request): terom@197: return self.open().read() terom@197: terom@197: TYPES = { terom@197: 'html': HTML_Page, terom@197: }