Package Products :: Package ZenUtils :: Package patches :: Module dirviewmonkey |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenUtils.patches.dirviewmonkey

      1  ##############################################################################
      2  #
      3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved.
      4  #
      5  # This content is made available according to terms specified in
      6  # License.zenoss under the directory where your Zenoss product is installed.
      7  #
      8  ##############################################################################
      9
     10
     11  """
     12  This module patches CMFCore DirectoryViews to allow unauthenticated users
     13  access to filesystem-based resources. This is necessary for ZenDeviceACL to
     14  function.
     15  """
     16
     17  #######################################################
     18  # DirectoryView imports
     19  #######################################################
     20  import logging
     21  from os import path
     22  from OFS.ObjectManager import bad_id
     23
     24  from Products.CMFCore.FSMetadata import FSMetadata
     25  from Products.CMFCore.FSObject import BadFile
     26
     27  logger = logging.getLogger('CMFCore.DirectoryView')
     28
     29  #######################################################
     30  # Imports from DirectoryView itself
     31  #######################################################
     32  from Products.CMFCore.DirectoryView import _filtered_listdir
     33  from Products.CMFCore.DirectoryView import DirectoryView
     34
     35  #######################################################
     36  # The only import we need
     37  #######################################################
     38  from Products.ZenUtils.Utils import monkeypatch
     39
     40  @monkeypatch(FSMetadata)
     41 -def read(self):
     42      """ Find the files to read, either the old security and
     43      properties type or the new metadata type """
     44      filename = self._filename + '.metadata'
     45      if path.exists(filename):
     46          # found the new type, lets use that
     47          self._readMetadata()
     48      else:
     49  ###########################################################################
     50  # This is a monkeypatch. CMFCore 2.0 returns {} where 1.x returned
     51  # None; we rely on None. {} is (maybe) ambiguous.
     52  ###########################################################################
     53          self._properties = None
     54          self._security = None
     55  ###########################################################################
     56  # End monkeypatch
     57  ###########################################################################
     58
     59
     60  @monkeypatch('Products.CMFCore.DirectoryView.DirectoryInformation')
     61 -def prepareContents(self, registry, register_subdirs=0):
     62      # Creates objects for each file.
     63      data = {}
     64      objects = []
     65      types = self._readTypesFile()
     66      for entry in _filtered_listdir(self._filepath, ignore=self.ignore):
     67          if not self._isAllowableFilename(entry):
     68              continue
     69          entry_filepath = path.join(self._filepath, entry)
     70          if path.isdir(entry_filepath):
     71              # Add a subdirectory only if it was previously registered,
     72              # unless register_subdirs is set.
     73              entry_reg_key = '/'.join((self._reg_key, entry))
     74              info = registry.getDirectoryInfo(entry_reg_key)
     75              if info is None and register_subdirs:
     76                  # Register unknown subdirs
     77                  registry.registerDirectoryByKey(entry_filepath,
     78                                                  entry_reg_key)
     79                  info = registry.getDirectoryInfo(entry_reg_key)
     80              if info is not None:
     81                  # Folders on the file system have no extension or
     82                  # meta_type, as a crutch to enable customizing what gets
     83                  # created to represent a filesystem folder in a
     84                  # DirectoryView we use a fake type "FOLDER". That way
     85                  # other implementations can register for that type and
     86                  # circumvent the hardcoded assumption that all filesystem
     87                  # directories will turn into DirectoryViews.
     88                  mt = types.get(entry) or 'FOLDER'
     89                  t = registry.getTypeByMetaType(mt)
     90                  if t is None:
     91                      t = DirectoryView
     92                  metadata = FSMetadata(entry_filepath)
     93                  metadata.read()
     94                  ob = t( entry
     95                        , entry_reg_key
     96                        , properties=metadata.getProperties()
     97                        )
     98                  ob_id = ob.getId()
     99                  data[ob_id] = ob
    100                  objects.append({'id': ob_id, 'meta_type': ob.meta_type})
    101          else:
    102              pos = entry.rfind('.')
    103              if pos >= 0:
    104                  name = entry[:pos]
    105                  ext = path.normcase(entry[pos + 1:])
    106              else:
    107                  name = entry
    108                  ext = ''
    109              if not name or name == 'REQUEST':
    110                  # Not an allowable id.
    111                  continue
    112              mo = bad_id(name)
    113              if mo is not None and mo != -1:  # Both re and regex formats
    114                  # Not an allowable id.
    115                  continue
    116              t = None
    117              mt = types.get(entry, None)
    118              if mt is None:
    119                  mt = types.get(name, None)
    120              if mt is not None:
    121                  t = registry.getTypeByMetaType(mt)
    122              if t is None:
    123                  t = registry.getTypeByExtension(ext)
    124
    125              if t is not None:
    126                  metadata = FSMetadata(entry_filepath)
    127                  metadata.read()
    128                  try:
    129                      ob = t(name, entry_filepath, fullname=entry,
    130                             properties=metadata.getProperties())
    131                  except:
    132                      import sys
    133                      import traceback
    134                      typ, val, tb = sys.exc_info()
    135                      try:
    136                          logger.exception("prepareContents")
    137
    138                          exc_lines = traceback.format_exception( typ,
    139                                                                  val,
    140                                                                  tb )
    141                          ob = BadFile( name,
    142                                        entry_filepath,
    143                                        exc_str='\r\n'.join(exc_lines),
    144                                        fullname=entry )
    145                      finally:
    146                          tb = None   # Avoid leaking frame!
    147
    148                  # FS-based security
    149                  permissions = metadata.getSecurity()
    150                  if permissions is not None:
    151                      for name in permissions.keys():
    152                          acquire, roles = permissions[name]
    153                          try:
    154                              ob.manage_permission(name,roles,acquire)
    155                          except ValueError:
    156                              logger.exception("Error setting permissions")
    157  ###########################################################################
    158  # This is the monkeypatch. These lines don't exist in CMFCore.  This allows
    159  # unauthenticated users to access filesystem-based resources like page
    160  # templates and static UI elements.
    161  ###########################################################################
    162                  else:
    163                      ob.manage_permission('View',('Authenticated',),1)
    164  ###########################################################################
    165  # End monkeypatch
    166  ###########################################################################
    167
    168                  # only DTML Methods and Python Scripts can have proxy roles
    169                  if hasattr(ob, '_proxy_roles'):
    170                      try:
    171                          ob._proxy_roles = tuple(metadata.getProxyRoles())
    172                      except:
    173                          logger.exception("Error setting proxy role")
    174
    175                  ob_id = ob.getId()
    176                  data[ob_id] = ob
    177                  objects.append({'id': ob_id, 'meta_type': ob.meta_type})
    178
    179      return data, tuple(objects)
    180