Hatta File Tree Branch
changeset 632:607a934cc6bb
Add support for docs/path/pages (docs tree)
| author | Randy Selzler <RS-merc@Data-Warp.com> |
|---|---|
| date | Mon Dec 21 11:08:18 2009 -0600 (2009-12-21) |
| parents | d973b363d32e |
| children | 9c8347beb368 |
| files | hatta.py |
line diff
1.1 --- a/hatta.py Thu Dec 03 01:31:43 2009 +0100 1.2 +++ b/hatta.py Mon Dec 21 11:08:18 2009 -0600 1.3 @@ -292,6 +292,8 @@ 1.4 """ 1.5 1.6 self.charset = charset or 'utf-8' 1.7 + # RegEx matching path components that contain ".." 1.8 + self.dot_dot_re = re.compile('(^|/)\.\.(?=(/|$))') 1.9 self.path = path 1.10 if not os.path.exists(self.path): 1.11 os.makedirs(self.path) 1.12 @@ -330,11 +332,17 @@ 1.13 return path 1.14 1.15 def _file_path(self, title): 1.16 - return os.path.join(self.path, werkzeug.url_quote(title, safe='')) 1.17 + if self.dot_dot_re.search(title): 1.18 + raise werkzeug.exceptions.Forbidden( 1.19 + u'_file_path: Link contains ".." components: %s' % title) 1.20 + return os.path.join(self.path, werkzeug.url_quote(title, safe='/')) 1.21 1.22 def _title_to_file(self, title): 1.23 + if self.dot_dot_re.search(title): 1.24 + raise werkzeug.exceptions.Forbidden( 1.25 + u'_title_to_file: Link contains "..": %s' % title) 1.26 return os.path.join(self.repo_prefix, 1.27 - werkzeug.url_quote(title, safe='')) 1.28 + werkzeug.url_quote(title, safe='/')) 1.29 1.30 def _file_to_title(self, filename): 1.31 assert filename.startswith(self.repo_prefix) 1.32 @@ -383,12 +391,28 @@ 1.33 @locked_repo 1.34 def save_file(self, title, file_name, author=u'', comment=u'', parent=None): 1.35 """Save an existing file as specified page.""" 1.36 + import errno 1.37 1.38 user = author.encode('utf-8') or _(u'anon').encode('utf-8') 1.39 text = comment.encode('utf-8') or _(u'comment').encode('utf-8') 1.40 repo_file = self._title_to_file(title) 1.41 file_path = self._file_path(title) 1.42 - mercurial.util.rename(file_name, file_path) 1.43 + path_dir = os.path.dirname(file_path) 1.44 + 1.45 + if os.path.isdir(file_path): 1.46 + raise werkzeug.exceptions.Forbidden( 1.47 + u'save_file: Page name is a directory: %s' % file_path) 1.48 + 1.49 + try: 1.50 + if not os.path.isdir(path_dir): 1.51 + os.makedirs(path_dir) 1.52 + mercurial.util.rename(file_name, file_path) 1.53 + except OSError, err: 1.54 + # Path component is an existing page? 1.55 + msg = u'save_file: [Errno %s] %s: in path %s' % (err.errno, 1.56 + os.strerror(err.errno), file_path) 1.57 + raise werkzeug.exceptions.Forbidden(msg) 1.58 + 1.59 changectx = self._changectx() 1.60 try: 1.61 filectx_tip = changectx[repo_file] 1.62 @@ -604,12 +628,15 @@ 1.63 yield title, rev, date, author, comment 1.64 1.65 def all_pages(self): 1.66 - """Iterate over the titles of all pages in the wiki.""" 1.67 - 1.68 - for filename in os.listdir(self.path): 1.69 - if (os.path.isfile(os.path.join(self.path, filename)) 1.70 - and not filename.startswith('.')): 1.71 - yield werkzeug.url_unquote(filename) 1.72 + """Iterate over the titles of all pages in the wiki tree.""" 1.73 + 1.74 + for dirpath, dirnames, filenames in os.walk(self.path): 1.75 + dirnames[:] = [d for d in dirnames if not d.startswith('.')] 1.76 + relpath = dirpath[len(self.path)+1:] 1.77 + for name in filenames: 1.78 + if (os.path.isfile(os.path.join(dirpath, name)) 1.79 + and not name.startswith('.')): 1.80 + yield werkzeug.url_unquote(os.path.join(relpath, name)) 1.81 1.82 def changed_since(self, rev): 1.83 """Return all pages that changed since specified repository revision.""" 1.84 @@ -2106,10 +2133,26 @@ 1.85 yield u'</table>' 1.86 1.87 class WikiTitleConverter(werkzeug.routing.PathConverter): 1.88 - """Behaves like the path converter, except that it escapes slashes.""" 1.89 + """Behaves like the path converter, except ".." components are rejected.""" 1.90 + 1.91 +# RLS, FIXME NOTE: to_url appears to control "Title" rendering at top of pages... 1.92 + 1.93 + def __init__FIXME_RLS(self, junk): 1.94 + # If __init__FIXME_RLS is changed to __init__ then the class 1.95 + # is initialized, but backlinks fail... Don't know why ! 2009-11-27 RLS 1.96 + """ 1.97 + Initialize for to_url and url_quote. 1.98 + """ 1.99 + # RegEx matching path components that contain ".." 1.100 + self.dot_dot_re = re.compile('(^|/)\.\.(?=(/|$))') 1.101 1.102 def to_url(self, value): 1.103 - return werkzeug.url_quote(value, self.map.charset, safe="") 1.104 + # Kludge because __init__ breaks backlinks. 1.105 + self.dot_dot_re = re.compile('(^|/)\.\.(?=(/|$))') 1.106 + if self.dot_dot_re.search(value): 1.107 + raise werkzeug.exceptions.Forbidden( 1.108 + u'to_url: Name contains ".." path component: %s' % value) 1.109 + return werkzeug.url_quote(value, self.map.charset, safe='/') 1.110 1.111 class WikiAllConverter(werkzeug.routing.BaseConverter): 1.112 """Matches everything.""" 1.113 @@ -2123,6 +2166,7 @@ 1.114 application and most of the logic. 1.115 """ 1.116 storage_class = WikiStorage 1.117 + titleConverter_class = WikiTitleConverter 1.118 index_class = WikiSearch 1.119 mime_map = { 1.120 'text': WikiPageText,
