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

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

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