Code

d73d7d86f30e826286c619a191030ed91b438c73
[roundup.git] / frontends / ZRoundup / ZRoundup.py
1 # Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
2 # This module is free software, and you may redistribute it and/or modify
3 # under the same terms as Python, so long as this copyright message and
4 # disclaimer are retained in their original form.
5 #
6 # IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
7 # DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
8 # OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
9 # POSSIBILITY OF SUCH DAMAGE.
10 #
11 # BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
12 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 # FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
14 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
15 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
16
17 # $Id: ZRoundup.py,v 1.3 2001-12-12 23:55:00 richard Exp $
18 #
19 ''' ZRoundup module - exposes the roundup web interface to Zope
21 This frontend works by providing a thin layer that sits between Zope and the regular CGI
22 interface of roundup, providing the web frontend with the minimum of effort.
24 This means that the regular CGI interface does all authentication quite independently of
25 Zope.
27 It also means that any requests which specify :filter, :columns or :sort _must_ be done
28 using a GET, so that this interface can re-parse the QUERY_STRING. Zope interprets the
29 ':' as a special character, and the special args are lost to it.
30 '''
31 from Globals import InitializeClass, HTMLFile
32 from OFS.SimpleItem import Item
33 from OFS.PropertyManager import PropertyManager
34 from Acquisition import Implicit
35 from Persistence import Persistent
36 from AccessControl import ClassSecurityInfo
37 from AccessControl import ModuleSecurityInfo
38 modulesecurity = ModuleSecurityInfo()
40 import roundup.instance
41 from roundup import cgi_client
43 modulesecurity.declareProtected('View management screens', 'manage_addZRoundupForm')
44 manage_addZRoundupForm = HTMLFile('dtml/manage_addZRoundupForm', globals())
46 modulesecurity.declareProtected('Add Z Roundups', 'manage_addZRoundup')
47 def manage_addZRoundup(self, id, instance_home, REQUEST):
48     """Add a ZRoundup product """
49     # validate the instance_home
50     roundup.instance.open(instance_home)
51     self._setObject(id, ZRoundup(id, instance_home))
52     return self.manage_main(self, REQUEST)
54 class RequestWrapper:
55     '''Make the Zope RESPONSE look like a BaseHTTPServer
56     '''
57     def __init__(self, RESPONSE):
58         self.RESPONSE = RESPONSE
59         self.wfile = self.RESPONSE
60     def send_response(self, status):
61         self.RESPONSE.setStatus(status)
62     def send_header(self, header, value):
63         self.RESPONSE.addHeader(header, value)
64     def end_headers(self):
65         # not needed - the RESPONSE object handles this internally on write()
66         pass
68 class FormItem:
69     '''Make a Zope form item look like a cgi.py one
70     '''
71     def __init__(self, value):
72         self.value = value
73         if hasattr(self.value, 'filename'):
74             self.filename = self.value.filename
75             self.file = self.value
77 class FormWrapper:
78     '''Make a Zope form dict look like a cgi.py one
79     '''
80     def __init__(self, form):
81         self.form = form
82     def __getitem__(self, item):
83         return FormItem(self.form[item])
84     def has_key(self, item):
85         return self.form.has_key(item)
86     def keys(self):
87         return self.form.keys()
89 class ZRoundup(Item, PropertyManager, Implicit, Persistent):
90     '''An instance of this class provides an interface between Zope and roundup for one
91        roundup instance
92     '''
93     meta_type =  'Z Roundup'
94     security = ClassSecurityInfo()
96     def __init__(self, id, instance_home):
97         self.id = id
98         self.instance_home = instance_home
100     # define the properties that define this object
101     _properties = (
102         {'id':'id', 'type': 'string', 'mode': 'w'},
103         {'id':'instance_home', 'type': 'string', 'mode': 'w'},
104     )
105     property_extensible_schema__ = 0
107     # define the tabs for the management interface
108     manage_options= PropertyManager.manage_options + (
109         {'label': 'View', 'action':'index_html'},
110     ) + Item.manage_options
112     icon = "misc_/ZRoundup/icon"
114     security.declarePrivate('_opendb')
115     def _opendb(self):
116         '''Open the roundup instance database for a transaction.
117         '''
118         instance = roundup.instance.open(self.instance_home)
119         request = RequestWrapper(self.REQUEST['RESPONSE'])
120         env = self.REQUEST.environ
121         env['INSTANCE_NAME'] = self.id
122         if env['REQUEST_METHOD'] == 'GET':
123             # force roundup to re-parse the request because Zope fiddles
124             # with it and we lose all the :filter, :columns, etc goodness
125             form = None
126         else:
127             form = FormWrapper(self.REQUEST.form)
128         return instance.Client(instance, request, env, form)
130     security.declareProtected('View', 'index_html')
131     def index_html(self):
132         '''Alias index_html to roundup's index
133         '''
134         client = self._opendb()
135         # fake the path that roundup should use
136         client.split_path = ['index']
137         return client.main()
139     def __getitem__(self, item):
140         '''All other URL accesses are passed throuh to roundup
141         '''
142         try:
143             client = self._opendb()
144             # fake the path that roundup should use
145             client.split_path = [item]
146             # and call roundup to do something 
147             client.main()
148             return ''
149         except cgi_client.NotFound:
150             raise 'NotFound', self.REQUEST.URL
151             pass
152         except:
153             import traceback
154             traceback.print_exc()
155             # all other exceptions in roundup are valid
156             raise
157         raise KeyError, item
160 InitializeClass(ZRoundup)
161 modulesecurity.apply(globals())
165 # $Log: not supported by cvs2svn $
166 # Revision 1.2  2001/12/12 23:33:58  richard
167 # added some implementation notes
169 # Revision 1.1  2001/12/12 23:27:13  richard
170 # Added a Zope frontend for roundup.
174 # vim: set filetype=python ts=4 sw=4 et si