"Fossies" - the Fresh Open Source Software Archive

Member "roundup-2.0.0/frontends/ZRoundup/ZRoundup.py" (26 Aug 2019, 7934 Bytes) of package /linux/www/roundup-2.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "ZRoundup.py": 1.6.1_vs_2.0.0.

    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 ''' ZRoundup module - exposes the roundup web interface to Zope
   18 
   19 This frontend works by providing a thin layer that sits between Zope and the
   20 regular CGI interface of roundup, providing the web frontend with the minimum
   21 of effort.
   22 
   23 This means that the regular CGI interface does all authentication quite
   24 independently of Zope. The roundup code is kept in memory though, and it
   25 runs in the same server as all your other Zope stuff, so it does have _some_
   26 advantages over regular CGI :)
   27 '''
   28 
   29 from roundup.anypy import urllib_
   30 
   31 from Globals import InitializeClass, HTMLFile
   32 from OFS.SimpleItem import Item
   33 from OFS.PropertyManager import PropertyManager
   34 from Acquisition import Explicit, Implicit
   35 from Persistence import Persistent
   36 from AccessControl import ClassSecurityInfo
   37 from AccessControl import ModuleSecurityInfo
   38 modulesecurity = ModuleSecurityInfo()
   39 
   40 import roundup.instance
   41 from roundup.cgi import client
   42 
   43 modulesecurity.declareProtected('View management screens',
   44     'manage_addZRoundupForm')
   45 manage_addZRoundupForm = HTMLFile('dtml/manage_addZRoundupForm', globals())
   46 
   47 modulesecurity.declareProtected('Add Z Roundups', 'manage_addZRoundup')
   48 def manage_addZRoundup(self, id, instance_home, REQUEST):
   49     """Add a ZRoundup product """
   50     # validate the instance_home
   51     roundup.instance.open(instance_home)
   52     self._setObject(id, ZRoundup(id, instance_home))
   53     return self.manage_main(self, REQUEST)
   54 
   55 class RequestWrapper:
   56     '''Make the Zope RESPONSE look like a BaseHTTPServer
   57     '''
   58     def __init__(self, RESPONSE):
   59         self.RESPONSE = RESPONSE
   60         self.wfile = self.RESPONSE
   61     def send_response(self, status):
   62         self.RESPONSE.setStatus(status)
   63     def send_header(self, header, value):
   64         self.RESPONSE.addHeader(header, value)
   65     def end_headers(self):
   66         # not needed - the RESPONSE object handles this internally on write()
   67         pass
   68     def start_response(self, headers, response):
   69         self.send_response(response)
   70         for key, value in headers:
   71             self.send_header(key, value)
   72         self.end_headers()
   73 
   74 class FormItem:
   75     '''Make a Zope form item look like a cgi.py one
   76     '''
   77     def __init__(self, value):
   78         self.value = value
   79         if hasattr(self.value, 'filename'):
   80             self.filename = self.value.filename
   81             self.value = self.value.read()
   82 
   83 class FormWrapper:
   84     '''Make a Zope form dict look like a cgi.py one
   85     '''
   86     def __init__(self, form):
   87         self.__form = form
   88     def __getitem__(self, item):
   89         entry = self.__form[item]
   90         if isinstance(entry, type([])):
   91             entry = list(map(FormItem, entry))
   92         else:
   93             entry = FormItem(entry)
   94         return entry
   95     def __iter__(self):
   96         return iter(self.__form)
   97     def getvalue(self, key, default=None):
   98         if key in self.__form:
   99             return self.__form[key]
  100         else:
  101             return default
  102     def has_key(self, item):
  103         return item in self.__form
  104     def keys(self):
  105         return list(self.__form.keys())
  106 
  107     def __repr__(self):
  108         return '<ZRoundup.FormWrapper %r>'%self.__form
  109 
  110 class ZRoundup(Item, PropertyManager, Implicit, Persistent):
  111     '''An instance of this class provides an interface between Zope and
  112        roundup for one roundup instance
  113     '''
  114     meta_type =  'Z Roundup'
  115     security = ClassSecurityInfo()
  116 
  117     def __init__(self, id, instance_home):
  118         self.id = id
  119         self.instance_home = instance_home
  120 
  121     # define the properties that define this object
  122     _properties = (
  123         {'id':'id', 'type': 'string', 'mode': 'w'},
  124         {'id':'instance_home', 'type': 'string', 'mode': 'w'},
  125     )
  126     property_extensible_schema__ = 0
  127 
  128     # define the tabs for the management interface
  129     manage_options= PropertyManager.manage_options + (
  130         {'label': 'View', 'action':'index_html'},
  131     ) + Item.manage_options
  132 
  133     icon = "misc_/ZRoundup/icon"
  134 
  135     security.declarePrivate('roundup_opendb')
  136     def roundup_opendb(self):
  137         '''Open the roundup instance database for a transaction.
  138         '''
  139         tracker = roundup.instance.open(self.instance_home)
  140         request = RequestWrapper(self.REQUEST['RESPONSE'])
  141         env = self.REQUEST.environ
  142 
  143         # figure out the path components to set
  144         url = urllib_.urlparse( self.absolute_url() )
  145         path = url[2]
  146         path_components = path.split( '/' )
  147 
  148         # special case when roundup is '/' in this virtual host,
  149         if path == "/" :
  150             env['SCRIPT_NAME'] = "/"
  151             env['TRACKER_NAME'] = ''
  152         else :
  153             # all but the last element is the path
  154             env['SCRIPT_NAME'] = '/'.join( path_components[:-1] )
  155             # the last element is the name
  156             env['TRACKER_NAME'] = path_components[-1]
  157 
  158         form = FormWrapper(self.REQUEST.form)
  159         if hasattr(tracker, 'Client'):
  160             return tracker.Client(tracker, request, env, form)
  161         return client.Client(tracker, request, env, form)
  162 
  163     security.declareProtected('View', 'index_html')
  164     def index_html(self):
  165         '''Alias index_html to roundup's index
  166         '''
  167         # Redirect misdirected requests -- bugs 558867 , 565992
  168         # PATH_INFO, as defined by the CGI spec, has the *real* request path
  169         orig_path = self.REQUEST.environ['PATH_INFO']
  170         if orig_path[-1] != '/' : 
  171             url = urllib_.urlparse( self.absolute_url() )
  172             url = list( url ) # make mutable
  173             url[2] = url[2]+'/' # patch
  174             url = urllib_.urlunparse( url ) # reassemble
  175             RESPONSE = self.REQUEST.RESPONSE
  176             RESPONSE.setStatus( "MovedPermanently" ) # 301
  177             RESPONSE.setHeader( "Location" , url )
  178             return RESPONSE
  179 
  180         client = self.roundup_opendb()
  181         # fake the path that roundup should use
  182         client.split_path = ['index']
  183         return client.main()
  184 
  185     def __getitem__(self, item):
  186         '''All other URL accesses are passed throuh to roundup
  187         '''
  188         return PathElement(self, item).__of__(self)
  189 
  190 class PathElement(Item, Implicit):
  191     def __init__(self, zr, path):
  192         self.zr = zr
  193         self.path = path
  194 
  195     def __getitem__(self, item):
  196         ''' Get a subitem.
  197         '''
  198         return PathElement(self.zr, self.path + '/' + item).__of__(self)
  199 
  200     def index_html(self, REQUEST=None):
  201         ''' Actually call through to roundup to handle the request.
  202         '''
  203         try:
  204             client = self.zr.roundup_opendb()
  205             # fake the path that roundup should use
  206             client.path = self.path
  207             # and call roundup to do something 
  208             client.main()
  209             return ''
  210         except client.NotFound:
  211             raise Exception('NotFound ' + REQUEST.URL)
  212             pass
  213         except:
  214             import traceback
  215             traceback.print_exc()
  216             # all other exceptions in roundup are valid
  217             raise
  218 
  219 InitializeClass(ZRoundup)
  220 modulesecurity.apply(globals())
  221 
  222 
  223 # vim: set filetype=python ts=4 sw=4 et si