removed obsolete issues (many of them fixed with AE)
[docutils.git] / sandbox / blais / rstserver / bin / rst-server.cgi
blob03cada1cc1a55e24fe7572e94eb5f24f62b88f92
1 #!/usr/bin/env python2
3 # $Id$
4 # $Source$
7 """docutils to HTML CGI converter.
9 CGI script that automatically converts docutils files into html and serves
10 it. The script caches the HTML files and uses the timestamps to regenerate if
11 necessary.  Also, the indexes are generated automatically.
14 """
16 __author__ = 'Martin Blais <blais@iro.umontreal.ca>'
17 __version__ = '$Revision$'
19 #===============================================================================
20 # EXTERNAL DECLARATIONS
21 #===============================================================================
23 import sys
24 assert sys.version_info[0] == 2
25 if sys.version_info[1] > 1:
26     import cgitb; cgitb.enable()
28 import os, cgi, stat, re
29 from os.path import *
30 import commands
31 from pprint import pprint
33 from ConfigParser import ConfigParser
34 #cgi.print_environ()
36 if not os.environ.has_key('NO_CONTENT_TYPE'):
37     print "Content-type: text/html"
40 #===============================================================================
41 # LOCAL DECLARATIONS
42 #===============================================================================
44 configfn = join(os.getcwd(), 'rst-server.conf')
45 if not exists(configfn):
46     print 'Error: config file "%s" does not exist' % configfn
47     sys.exit(1)
49 confparser = ConfigParser()
50 confparser.add_section('options')
51 confparser.read(configfn)
53 class Dummy: pass
54 opts = Dummy()
56 for o in ['source', 'cache', 'converter']:
57     if not confparser.has_option('options', o):
58         print 'Error: must configure variable', o
59         raise SystemExit()
60     setattr(opts, o.replace('-', '_'), confparser.get('options', o))
62 for o in ['docutils-config']:
63     val = None
64     if confparser.has_option('options', o):
65         val = confparser.get('options', o)
66     setattr(opts, o.replace('-', '_'), val)
68 form = cgi.FieldStorage()
69 if form.has_key('p'):
70     fn = form["p"].value
71 else:
72     fn = ''
74 if os.environ.has_key('CONVERTER'):
75     opts.converter = os.environ['CONVERTER']
77 # if from_php:
78 #     if len(sys.argv) > 1:
79 #         fn = sys.argv[1]
81 #===============================================================================
82 # LOCAL DECLARATIONS
83 #===============================================================================
85 rootstr = '(notes)'
87 rejre = map(re.compile, ['^\s*[-=]+\s*$', '^\.\.', '^\s*$', '\s*:\w+:'])
89 def gettitle( fn ):
91     #print '<pre>'
92     try:
93         f = open(fn, 'r')
94         while 1:
95             l = f.readline()
96             if not l:
97                 break
98             rej = 0
99             for r in rejre:
100                 if r.match(l):
101                     rej = 1
102                     break
103             if rej:
104                 #print l
105                 continue
107             title = l.strip()
108             break
109         f.close()
110     except:
111         title = fn
112     #print '</pre>'
114     # prevent tag-only titles, at least we'll get an error message
115     if title[0] == '<' and title[-1] == '>':
116         title = title[1:-1]
117     return title
119 valre = re.compile('(.*)\.txt')
121 def nav( fn, script ):
122     if fn and isfile(join(opts.source, fn)):
123         mo = valre.match(fn)
124         assert(mo)
125         fn = mo.group(1)
126     
127     comps = []
128     if fn:
129         fn = normpath(fn)
130         comps += fn.split(os.sep)
132     print '<table class="toptable">'
133     print '<tr><td>'
134     ccomps = []
135     cpath = ''
136     if comps:
137         for i in comps[0:-1]:
138             cpath = join(cpath, i)
139             ccomps.append('<a href="%s?p=%s">%s</a>' % (script, cpath, i))
140         ccomps.append('%s' % comps[-1])
141     ccomps = ['<a href="%s">%s</a>' % (script, rootstr)] + ccomps
142     print '&nbsp;&raquo;&nbsp;'.join(ccomps)
143     print '</td></tr>'
144     print '</table>'
146 print """
147 <?xml version="1.0" encoding="iso8859-1" ?>
148 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
149 <html>
150 <head>
151   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
152   <meta name="GENERATOR" content="home made recipe in python">
153    <style type="text/css"><!--
155 .toptable {
156    width: 100%;
157    background-color: #EEEEEE }
159 .sep {
160    width: 100px }
161    
162 .conversion-error {
163    background-color: #FF8888;
164    margin: 0.5em;
165    padding: 1em }
167 --></style>
168 </head>
170 <body>
175 script = os.environ['SCRIPT_NAME']
177 # make sure the cache directory exists
178 if not exists(opts.cache):
179     os.mkdir(opts.cache)
181 if fn:
182     srcfn = join(opts.source, fn)
183 else:
184     srcfn = opts.source
186 nav(fn, script)
188 class Page:
189     def __init__( self, fn, base ):
190         self.fn = fn
191         self.base = base
192         self.title = base
194 if not exists(srcfn):
195     print 'Error: this file does not exist'
196 else:    
197     if isdir(srcfn):
198         #cachefn = join(cache, fn, 'index.html')
199         
200         files, dirs = [], []
201         for f in os.listdir(srcfn):
202             if f.startswith('.') or f.startswith('#'):
203                 continue
204             if f == 'CVS':
205                 continue
206             af = join(srcfn, f)
207             if isfile(af):
208                 mo = valre.match(f)
209                 if mo:
210                     files.append( Page(f, mo.group(1)) )
211             elif isdir(af):
212                 dirs.append(f)
214         print '<ul>'
215         for f in files:
216             f.title = gettitle(join(srcfn, f.fn))
217         files.sort(lambda x, y: cmp(x.title, y.title))
219         for f in files:
220             print '<li><a href="%s?p=%s">%s</li>' % \
221                   (script, join(fn, f.fn), f.title)
222         print '</ul>'
224         print '<ul>'
225         for f in dirs:
226             print '<li><a href="%s?p=%s">%s</li>' % (script, join(fn, f), f)
227         print '</ul>'
228     else:
229         if not fn.endswith('.txt'):
230             print 'request for file not ending in .txt', fn
231             sys.exit(0)
233         cachefn = join(opts.cache, '%s.html' % splitext(fn)[0])
234         regen = 1
235         if exists(srcfn) and exists(cachefn):
236             fnstat, cachestat = map(os.stat, [srcfn, cachefn])
237             if fnstat[stat.ST_MTIME] <= cachestat[stat.ST_MTIME]:
238                 # use cache
239                 regen = 0
241         if regen:
242             cachedir = dirname(cachefn)
243             if not exists(cachedir):
244                 os.makedirs(cachedir)
245             
246             cmd = opts.converter
247             if opts.docutils_config:
248                 cmd += ' --config="%s"' % opts.docutils_config
249             cmd += ' "%s" "%s" 2>&1' % (srcfn, cachefn)
250             if 0:
251                 chin, chout, cherr = os.popen3(cmd)
252                 chin.close()
253                 err = chout.read()
254                 out = chout.read()
255             else:
256                 s, out = commands.getstatusoutput(cmd)
257                 if out:
258                     print '<div class="conversion-error">'
259                     print 'Error: converting document:'
260                     print '<pre>'
261                     print out
262                     print '</pre>'
263                     print '</div>'
264                     
266         print open(cachefn, 'r').read()
268 print """
269 </body>
270 </html>