File: Synopsis/Formatters/HTML/Views/Directory.py
  1#
  2# Copyright (C) 2000 Stephen Davies
  3# Copyright (C) 2000 Stefan Seefeld
  4# All rights reserved.
  5# Licensed to the public under the terms of the GNU LGPL (>= 2),
  6# see the file COPYING for details.
  7#
  8
  9from Synopsis import config
 10from Synopsis.Processor import Parameter
 11from Synopsis.Formatters.HTML.View import View
 12from Synopsis.Formatters.HTML.Tags import *
 13import os, stat, os.path, time, re
 14
 15def compile_glob(globstr):
 16    """Returns a compiled regular expression for the given glob string. A
 17    glob string is something like "*.?pp" which gets translated into
 18    "^.*\..pp$"."""
 19    glob = globstr.replace('.', '\.')
 20    glob = glob.replace('?', '.')
 21    glob = glob.replace('*', '.*')
 22    glob = re.compile('^%s$'%glob)
 23    return glob
 24
 25class Directory(View):
 26    """A view that lists the content of a directory."""
 27
 28    src_dir = Parameter('', 'starting point for directory listing')
 29    base_path = Parameter('', 'path prefix to strip off of the file names')
 30    exclude = Parameter([], 'TODO: define an exclusion mechanism (glob based ?)')
 31
 32    def filename(self):
 33
 34        return self.__filename
 35
 36    def title(self):
 37
 38        return 'Directory Listing'
 39
 40    def root(self):
 41
 42        if self.main:
 43            url = self.directory_layout.index()
 44        else:
 45            url = self.directory_layout.special('dir')
 46        return url, self.title()
 47
 48    def filename_for_dir(self, dir):
 49        """Returns the output filename for the given input directory."""
 50
 51        if dir == self.src_dir:
 52            return self.root()[0]
 53        else:
 54            scope = rel(self.src_dir, dir).split(os.sep)
 55            return self.directory_layout.scoped_special('dir', scope)
 56
 57    def register(self, frame):
 58
 59        View.register(self, frame)
 60        self._exclude = [compile_glob(e) for e in self.exclude]
 61        self.__filename = self.root()[0]
 62
 63    def register_filenames(self):
 64
 65        dirs = [self.src_dir]
 66        while dirs:
 67            dir = dirs.pop(0)
 68            for entry in os.listdir(os.path.abspath(dir)):
 69                exclude = 0
 70                for re in self._exclude:
 71                    if re.match(entry):
 72                        exclude = 1
 73                        break
 74                if exclude:
 75                    continue
 76                entry_path = os.path.join(dir, entry)
 77                if os.path.isdir(entry_path):
 78                    filename = self.filename_for_dir(dir)
 79                    self.processor.register_filename(filename, self, entry_path)
 80                    dirs.append(entry_path)
 81
 82    def process(self):
 83
 84        self.process_dir(self.src_dir)
 85
 86    def process_dir(self, path):
 87
 88        # Find the filename
 89        self.__filename = self.filename_for_dir(path)
 90
 91        # Start the file
 92        self.start_file()
 93        self.write_navigation_bar()
 94        # Write intro stuff
 95        root = ''
 96        if self.base_path != self.src_dir:
 97            rel(self.base_path, self.src_dir)
 98        if not len(root) or root[-1] != '/': root = root + '/'
 99        if path is self.src_dir:
100            self.write('<h1> '+root)
101        else:
102            self.write('<h1>' + href(self.root()[0], root + ' '))
103            dirscope = []
104            scope = rel(self.src_dir, path).split(os.sep)
105
106            for dir in scope[:-1]:
107                dirscope.append(dir)
108                dirlink = self.directory_layout.scoped_special('dir', dirscope)
109                dirlink = rel(self.filename(), dirlink)
110
111                self.write(href(dirlink, dir+'/ '))
112            if len(scope) > 0:
113                self.write(scope[-1]+'/')
114        self.write(' - Directory listing</h1>')
115        # Start the table
116        self.write('<table summary="Directory Listing">\n')
117        self.write('<tr><th align=left>Name</th>')
118        self.write('<th align="right">Size (bytes)</th>')
119        self.write('<th align="right">Last modified (GMT)</th></tr>\n')
120        # List all files in the directory
121        entries = os.listdir(os.path.abspath(path))
122        entries.sort()
123        files = []
124        dirs = []
125        for entry in entries:
126         exclude = 0
127         for re in self._exclude:
128            if re.match(entry):
129               exclude = 1
130               break
131         if exclude:
132            continue
133         entry_path = os.path.join(path, entry)
134         info = os.stat(entry_path)
135         if stat.S_ISDIR(info[stat.ST_MODE]):
136            # A directory, process now
137            scope = rel(self.src_dir, entry_path).split(os.sep)
138            linkpath = self.directory_layout.scoped_special('dir', scope)
139            linkpath = rel(self.filename(), linkpath)
140            self.write('<tr><td>%s</td><td></td><td align="right">%s</td></tr>\n'%(
141               href(linkpath, entry+'/'),
142               time.asctime(time.gmtime(info[stat.ST_MTIME]))))
143            dirs.append(entry_path)
144         else:
145            files.append((entry_path, entry, info))
146
147        for path, entry, info in files:
148            size = info[stat.ST_SIZE]
149            timestr = time.asctime(time.gmtime(info[stat.ST_MTIME]))
150            # strip of base_path
151            path = path[len(self.base_path):]
152            if path[0] == '/': path = path[1:]
153            linkpath = self.directory_layout.file_source(path)
154            rego = self.processor.filename_info(linkpath)
155            if rego:
156                linkurl = rel(self.filename(), linkpath)
157                self.write('<tr><td>%s</td><td align="right">%d</td><td align="right">%s</td></tr>\n'%(
158                    href(linkurl, entry, target='content'), size, timestr))
159            else:
160                # print "No link for",linkpath
161                self.write('<tr><td>%s</td><td align="right">%d</td><td align="right">%s</td></tr>\n'%(
162                    entry, size, timestr))
163        # End the table and file
164        self.write('</table>')
165        self.end_file()
166
167        # recursively create all child directory views
168        for dir in dirs:
169            self.process_dir(dir)
170
171    def end_file(self):
172        """Overrides end_file to provide synopsis logo"""
173
174        self.write('\n')
175        now = time.strftime(r'%c', time.localtime(time.time()))
176        logo = img(src=rel(self.filename(), 'synopsis.png'), alt='logo')
177        logo = href('http://synopsis.fresco.org', logo + ' synopsis', target='_blank')
178        logo += ' (version %s)'%config.version
179        self.write(div('logo', 'Generated on ' + now + ' by \n<br/>\n' + logo))
180        View.end_file(self)
181