import make_schema_doc import schema_remarks import cgi import os import re import string import StringIO import sys import time import urllib # 1. GENERIC CGI SUPPORT FOR RAVENBROOK # # Adapted from issue.cgi. # # Objects belonging to the webpage class output a web page when their # print_page() method is called. Methods starting print_ actually print # to stdout whereas methods starting prepare_ only prepare some portion # of the output. Subclasses of webpage should override the # prepare_body() method so that it constructs an appropriate body for # the web page (by making a series of calls to the b() method to # accumulate lines of body text). # # The reason for constructing the whole body before printing anything is # so that errors can be handled simply gracefully. A method that # encounters an error should call # # raise error, (status, status_message, error_message) # # The status and status_message arguments to the error are used to make # the HTTP status header: for example (404, 'Not found') or (400, # 'Missing form parameter'). See [RFC 2616] for HTTP status codes. The # status_message is also used to make the page's title. The # error_message is used for the body of the page. # # The script supports two behaviours for other errors: # # 1. Leave them uncaught, causing the script to crash and an HTTP error # log entry to be written by Apache. # # 2. Generate an error page as if by raise error, (500, 'Python error', # exc_type + ': ' + exc_value). # # It's a security risk to give out detailed information about errors, so # we use (1) on the public server and (2) on the internal server. # # The directory_links list is used to build the list of links in the # header and footer of the outputted web page in the usual Ravenbrook # format. It is a list of pairs of (directory, description). # # This could be separated out into a module of its own. error = 'error' class webpage: body = '' # Page body body = None # Body of page: list of strings. directory_links = None # Directories to link to in header, footer h1 = None # Top-level header (if None, use title) status = 200 # HTTP status of output status_message = 'OK' # Message to go with the status title = 'Web page' # Page title debug_messages = [] # no debug messages yet! debug_level = 0 # don't accumulate any debug messages def __init__(self): self.body = [] self.title = "Default webpage title" self.debug_messages = [] self.debug_level = 0 self.directory_links = [ ( '', 'Ravenbrook' ), ( 'project', 'Projects' ), ( 'p4dti', 'Perforce Defect Tracking Integration' ), ( 'tool', 'Tools' ), ] # Append a line of HTML to the body of the webpage. def b(self, s): self.body.append(s) # Check that the form parameters are correct. This is a placeholder # that should be overridden in subclasses of webpage. def check_form_parameters(self): pass # Check and obtain the debugging level. This is a placeholder that # should be overridden in subclasses of webpage. def check_debug_level(self): pass # Print an 'Expires' header [RFC 2616, 14.21] specifying that the # page expires at midnight tonight. The reason for expiring the # output is that the same query to this script (e.g., action=list) # may generate different output each time it's called. Pages # lasting for a day means that people won't be misled by a cached # result from a long time ago. The format for the date is specified # in [RFC 822, 5.1] and modified by [RFC 1123, 5.2.14]; a date looks # like "Thu, 01 Dec 1994 16:00:00 GMT". def print_expires(self): print 'Expires:', print time.strftime("%a, %d %b %Y 00:00:00 GMT", time.gmtime(time.time() + 60*60*24)) # Prepare the body of the webpage by making calls to the b() method. # This is a placeholder that should be overridden in subclasses of # webpage. def prepare_body(self): pass # Print the directory links that go at the top and bottom of the # page. def print_directory_links(self): print '
' url = '' separator = '' for dir, name in self.directory_links: url = url + dir + '/' print '%s%s' % (separator, url, name) separator = '/ ' print '
' # Print the start of the webpage: the HTTP headers, the XML # declaration, the XHTML document type, the HTML ') print 'This document is copyright © 2001-2004 ' 'Perforce Software, Inc. All rights reserved.
\n') print ('Redistribution and use of this document in any form, ' 'with or without modification, is permitted provided that ' 'redistributions of this document retain the above copyright ' 'notice, this condition and the following disclaimer.
\n') print('This document is provided by the copyright ' 'holders and contributors "as is" and any express or implied ' 'warranties, including, but not limited to, the implied warranties ' 'of merchantability and fitness for a particular purpose are ' 'disclaimed. In no event shall the copyright holders and ' 'contributors be liable for any direct, indirect, incidental, ' 'special, exemplary, or consequential damages (including, but ' 'not limited to, procurement of substitute goods or services; ' 'loss of use, data, or profits; or business interruption) ' 'however caused and on any theory of liability, whether in ' 'contract, strict liability, or tort (including negligence or ' 'otherwise) arising in any way out of the use of this document, ' 'even if advised of the possibility of such damage. ' '
\n') def log(self, level, message): if level <= self.debug_level: self.debug_messages.append(message) # Print any accumulated debugging log. def print_debug(self): if self.debug_level > 0: if self.debug_messages: print 'element, # the directory links and the title. def print_header(self): print 'Status:', self.status, self.status_message print 'Content-Type: text/html' print print '' print ('') print ('') print '
' print '
' print '' print ('