class Connection(Shared.DC.ZRDB.Connection.Connection): _isAnSQLConnection = 1 manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options + ( { 'label': 'Browse', 'action': 'manage_browse' }, # {'label': 'Design', 'action':'manage_tables'}, ) manage_tables = HTMLFile('tables', globals()) manage_browse = HTMLFile('browse', globals()) info = None def tpValues(self): #if hasattr(self, '_v_tpValues'): return self._v_tpValues r = [] # self._v_tables=tables=TableBrowserCollection() #tables=tables.__dict__ c = self._v_database_connection try: for d in c.tables(rdb=0): try: name = d['TABLE_NAME'] b = TableBrowser() b.__name__ = name b._d = d b._c = c #b._columns=c.columns(name) b.icon = table_icons.get(d['TABLE_TYPE'], 'text') r.append(b) # tables[name]=b except: # print d['TABLE_NAME'], sys.exc_type, sys.exc_value pass finally: pass #print sys.exc_type, sys.exc_value #self._v_tpValues=r return r def __getitem__(self, name): if name == 'tableNamed': if not hasattr(self, '_v_tables'): self.tpValues() return self._v_tables.__of__(self) raise KeyError, name def manage_wizard(self, tables): " " def manage_join(self, tables, select_cols, join_cols, REQUEST=None): """Create an SQL join""" def manage_insert(self, table, cols, REQUEST=None): """Create an SQL insert""" def manage_update(self, table, keys, cols, REQUEST=None): """Create an SQL update"""
class YTombola( Tombola, # A classe que interessa! OFS.SimpleItem.Item, # A simple Principia object. Not Folderish. Persistent, # Make us persistent. Yaah! Acquisition.Implicit, # Uh, whatever. AccessControl.Role.RoleManager # Security manager. ): """Tombola class.""" meta_type = 'YTombola' def __init__(self, id, title, bolas): """initialise a new instance of Tombola""" self.id = id self.title = title Tombola.__init__(self, bolas) manage_options = ( { 'label': 'Edit', 'action': 'manage_main' }, { 'label': 'View', 'action': '' }, # defaults to index_html { 'label': 'Security', 'action': 'manage_access' }, { 'label': 'Sortear', 'action': 'sortear' }, ) __ac_permissions__ = ( ('View management screens', ('manage_tabs', 'manage_main')), ('Change permissions', ('manage_access', )), ('Change Tômbola', ('manage_edit', )), ('View Tômbola', ('', )), ('Use Tômbola', ('sortear', )), ) index_html = HTMLFile('index', globals()) # View Interface manage_main = HTMLFile('tombolaEdit', globals()) # Management Interface def manage_edit(self, title, bolas, REQUEST=None): """proc""" self.title = title self.bolas = bolas if REQUEST is not None: return MessageDialog( title='Edited', message="Properties for %s changed." % self.id, action='./manage_main', )
class TableBrowser(Browser, Acquisition.Implicit): icon='what' Description=check='' info=HTMLFile('dtml/table_info',globals()) menu=HTMLFile('dtml/table_menu',globals()) def tpValues(self): r=[] tname=self.__name__ for d in self._c.columns(tname): b=ColumnBrowser() b._d=d try: b.icon=field_icons[d['Type']] except: pass b.TABLE_NAME=tname r.append(b) return r def tpId(self): return self._d['TABLE_NAME'] def tpURL(self): return "Table/%s" % self._d['TABLE_NAME'] def Name(self): return self._d['TABLE_NAME'] def Type(self): return self._d['TABLE_TYPE'] manage_designInput=HTMLFile('dtml/designInput',globals()) def manage_buildInput(self, id, source, default, REQUEST=None): "Create a database method for an input form" args=[] values=[] names=[] columns=self._columns for i in range(len(source)): s=source[i] if s=='Null': continue c=columns[i] d=default[i] t=c['Type'] n=c['Name'] names.append(n) if s=='Argument': values.append("<dtml-sql-value %s type=%s>'" % (n, vartype(t))) a='%s%s' % (n, boboType(t)) if d: a="%s=%s" % (a,d) args.append(a) elif s=='Property': values.append("<dtml-sql-value %s type=%s>'" % (n, vartype(t))) else: if isStringType(t): if find(d,"\'") >= 0: d=join(split(d,"\'"),"''") values.append("'%s'" % d) elif d: values.append(str(d)) else: raise ValueError, ( 'no default was given for <em>%s</em>' % n)
class Connection(DABase.Connection): " " database_type = database_type id = '%s_database_connection' % database_type meta_type = title = 'Z %s Database Connection' % database_type icon = 'misc_/Z%sDA/conn' % database_type manage_properties = HTMLFile('connectionEdit', globals()) def factory(self): return DB def connect(self, s): try: self._v_database_connection.close() except: pass self._v_connected = '' DB = self.factory() ## No try. DO. self._v_database_connection = DB(s) self._v_connected = DateTime() return self def sql_quote__(self, v, escapes={}): return self._v_database_connection.string_literal(v)
class TableBrowser(Browser, Acquisition.Implicit): icon = 'what' Description = check = '' info = HTMLFile('table_info', globals()) menu = HTMLFile('table_menu', globals()) def tpValues(self): v = values() v._f = self.tpValues_ return v def tpValues_(self): r = [] tname = self.__name__ for d in self._c.columns(tname): b = ColumnBrowser() b._d = d try: b.icon = field_icons[d['Type']] except: pass b.TABLE_NAME = tname r.append(b) return r def tpId(self): return self._d['TABLE_NAME'] def tpURL(self): return "Table/%s" % self._d['TABLE_NAME'] def Name(self): return self._d['TABLE_NAME'] def Type(self): return self._d['TABLE_TYPE'] manage_designInput = HTMLFile('designInput', globals()) @staticmethod def vartype(inVar): "Get a type name for a variable suitable for use with dtml-sqlvar" outVar = type(inVar) if outVar == 'str': outVar = 'string' return outVar def manage_buildInput(self, id, source, default, REQUEST=None): "Create a database method for an input form" args = [] values = [] names = [] columns = self._columns for i in range(len(source)): s = source[i] if s == 'Null': continue c = columns[i] d = default[i] t = c['Type'] n = c['Name'] names.append(n) if s == 'Argument': values.append("<dtml-sqlvar %s type=%s>'" % (n, self.vartype(t))) a = '%s%s' % (n, self.vartype(t).title()) if d: a = "%s=%s" % (a, d) args.append(a) elif s == 'Property': values.append("<dtml-sqlvar %s type=%s>'" % (n, self.vartype(t))) else: if isinstance(t, basestring): if d.find("\'") >= 0: d = "''".join(d.split("\'")) values.append("'%s'" % d) elif d: values.append(str(d)) else: raise ValueError('no default was given for <em>%s</em>' % n)
# # $Id$ __doc__ = """HTMLWidget Fileupload module.""" __version__ = '2.1' import OFS.SimpleItem import Acquisition import AccessControl import ZPublisher.HTTPRequest from Globals import HTMLFile, MessageDialog, Persistent, InitializeClass from WidgetBase import WidgetBase, ValidationError, TALESMethod from IWidget import IWidget manage_addHTMLFileuploadForm = HTMLFile('dtml/HTMLFileuploadAdd', globals()) def manage_addHTMLFileupload(self, id, REQUEST=None): """ This will instanciate a new Fileupload Widget in the ZODB""" self._setObject(id, HTMLFileupload(id, REQUEST)) if REQUEST is not None: REQUEST.RESPONSE.redirect(self.absolute_url() + "/manage_visualEdit") class HTMLFileupload(WidgetBase, OFS.SimpleItem.Item, Persistent, Acquisition.Implicit, AccessControl.Role.RoleManager): """HTMLWidget for Fileuploads""" __implements__ = IWidget
self, p, title, description, email_from_address, email_from_name, validate_email, ): p._setProperty('email_from_address', email_from_address, 'string') p._setProperty('email_from_name', email_from_name, 'string') p._setProperty('validate_email', validate_email and 1 or 0, 'boolean') p.title = title p.description = description manage_addCMFSiteForm = HTMLFile('dtml/addPortal', globals()) manage_addCMFSiteForm.__name__ = 'addPortal' def manage_addCMFSite(self, id, title='Portal', description='', create_userfolder=1, email_from_address='postmaster@localhost', email_from_name='Portal Administrator', validate_email=0, RESPONSE=None): ''' Adds a portal instance. '''
for perm in ac_inherited_permissions(ob, 1): name, value = perm[:2] if map.has_key(name): for (role, allow) in map[name].items(): p = Permission(name, value, ob) p.setRole(role, allow) # Will only modify if it should. del map[name] if map: for name, (role, allow) in map.items(): p = Permission(name, (), ob) p.setRole(role, allow) from Globals import HTMLFile addInstanceForm = HTMLFile('dtml/addInstance', globals()) class ToolInit: '''Utility class that can generate the factories for several tools at once.''' __name__ = 'toolinit' security = ClassSecurityInfo() security.declareObjectPrivate() # equivalent of __roles__ = () def __init__(self, meta_type, tools, product_name, icon): '' self.meta_type = meta_type self.tools = tools self.product_name = product_name
class HTMLLabel(WidgetBase, OFS.SimpleItem.Item, Persistent, Acquisition.Implicit, AccessControl.Role.RoleManager): """HTMLWidget for Labels""" __implements__ = IWidget security = AccessControl.ClassSecurityInfo() meta_type = 'HTML Label' css_class = 'FormLabel' user_css = "" colspan = -1 aliases = [] security.declareProtected('View management screens', 'manage_properties') manage_properties = HTMLFile('dtml/HTMLLabelEdit', globals()) manage_options = ( { 'label': 'Properties', 'action': 'manage_properties' }, { 'label': 'Security', 'action': 'manage_access' }, ) ########### Zopish management stuff def __init__(self, id, REQUEST=None): self.id = id self.__version__ = __version__ if REQUEST is not None: self.changeProperties(REQUEST) security.declareProtected('Change Formulon instances', 'manage_edit') def manage_edit(self, REQUEST=None): """ set the new properties """ if REQUEST is not None: self.changeProperties(REQUEST) return MessageDialog(title='Edited', message="Properties for %s changed." % (self.id, ), action='./manage_properties') security.declareProtected('Change Formulon instances', 'changeProperties') def changeProperties(self, REQUEST=None, encoding='iso-8859-1'): if REQUEST is not None: # Update the base properties self.changeBaseProperties(REQUEST, encoding) self.value = unicode(REQUEST.value, encoding) self.title = self.value self.column = REQUEST.column self.user_css = REQUEST.user_css if self.column < 1: self.column = 1 self.row = REQUEST.row if self.row < 1: self.row = 1 self.colspan = REQUEST.colspan def title_or_id(self): assert isinstance(self.value, unicode) return self.value security.declareProtected('View', 'validate') def validate(self, against): return against security.declareProtected('View', 'height') def height(self): return 1 security.declareProtected('View', 'render') def render(self, parent, tabindex=None): node = parent.appendChild(parent.ownerDocument.createElement("span")) if self.user_css: node.setAttribute("class", self.user_css) else: node.setAttribute("class", self.css_class) node.appendChild(parent.ownerDocument.createTextNode(self.value)) return node security.declareProtected('View', 'getValue') def getValue(self): return None
p = parent.this()._getOb(id) self.setup(p, create_userfolder) return p def setupDefaultProperties(self, p, title, description, email_from_address, email_from_name, validate_email, ): p._setProperty('email_from_address', email_from_address, 'string') p._setProperty('email_from_name', email_from_name, 'string') p._setProperty('validate_email', validate_email and 1 or 0, 'boolean') p.title = title p.description = description manage_addCMFSiteForm = HTMLFile('dtml/addPortal', globals()) manage_addCMFSiteForm.__name__ = 'addPortal' def manage_addCMFSite(self, id, title='Portal', description='', create_userfolder=1, email_from_address='postmaster@localhost', email_from_name='Portal Administrator', validate_email=0, RESPONSE=None): ''' Adds a portal instance. ''' gen = PortalGenerator() id = id.strip() p = gen.create(self, id, create_userfolder) gen.setupDefaultProperties(p, title, description, email_from_address, email_from_name,
__version__ = '0.1' from Tombola import Tombola from Globals import HTMLFile # fakes a method from a DTML file from Globals import MessageDialog # provides Zope message dialogs from Globals import Persistent # makes an object stick in the ZODB import OFS.SimpleItem import Acquisition import AccessControl.Role from whrandom import random manage_addForm = HTMLFile('tombolaAdd', globals()) def manage_add(self, id, title='', REQUEST=None): """Add a Tombola to a folder.""" self._setObject(id, YTombola(id, title, REQUEST['bolas'])) if REQUEST is not None: return self.manage_main(self, REQUEST) class YTombola( Tombola, # A classe que interessa! OFS.SimpleItem.Item, # A simple Principia object. Not Folderish. Persistent, # Make us persistent. Yaah! Acquisition.Implicit, # Uh, whatever. AccessControl.Role.RoleManager # Security manager.
class Dumper(SimpleItem): """ """ meta_type = 'Dumper' manage_options = ({ 'label': 'Edit', 'action': 'editForm' }, { 'label': 'Security', 'action': 'manage_access' }) __ac__permissions = (('Use Dumper', ('editForm', 'edit', 'dumpToFS'), ('Manager', ))) fspath = None # # Management interface methods. # index_html = None editForm = HTMLFile('editDumper', _dtmldir) def edit(self, fspath, REQUEST=None): """ Update the path to which we will dump our peers. """ self._setFSPath(fspath) if REQUEST is not None: REQUEST['RESPONSE'].redirect( self.absolute_url() + '/editForm' + '?manage_tabs_message=Dumper+updated.') def dumpToFS(self, REQUEST=None): """ Iterate recursively over our peers, creating simulacra of them on the filesystem in 'fspath' """ if REQUEST and REQUEST.form.has_key('fspath'): self._setFSPath(REQUEST.form['fspath']) self._dumpFolder(self.aq_parent) if REQUEST is not None: REQUEST['RESPONSE'].redirect(self.absolute_url() + '/editForm' + '?manage_tabs_message=Peers+dumped.') # # Utility methods # def _setFSPath(self, fspath): # Canonicalize fspath. fspath = os.path.normpath(fspath) if fspath[0] != '/': raise "Dumper Error", "Path must be absolute." self.fspath = fspath def _buildPathString(self, path=None): # Construct a path string, relative to self.fspath. if self.fspath is None: raise "Dumper Error", "Path not set." if path is None: path = self.fspath else: path = os.path.normpath(os.path.join(self.fspath, path)) return path def _checkFSPath(self, path=None): # Ensure that fspath/path exists. path = self._buildPathString(path) if not os.path.exists(path): os.makedirs(path) return path def _createFile(self, path, filename, mode='w'): # Create/replace file; return the file object. fullpath = "%s/%s" % (self._checkFSPath(path), filename) return open(fullpath, mode) def _dumpObject(self, object, path=None): # Dump one item, using path as prefix. try: handler = self._handlers.get(object.meta_type, None) if handler is not None: handler(self, object, path) return 1 except: return -1 return 0 def _dumpObjects(self, objects, path=None): # Dump each item, using path as prefix. dumped = [] for object in objects: if self._dumpObject(object, path) > 0: id = object.id if callable(id): id = id() dumped.append((id, object.meta_type)) return dumped def _writeProperties(self, obj, file): propIDs = obj.propertyIds() propIDs.sort() # help diff out :) for propID in propIDs: type = obj.getPropertyType(propID) value = obj.getProperty(propID) file.write('%s:%s=%s\n' % (propID, type, value)) # # Type-specific dumpers # def _dumpFolder(self, obj, path=None): # Recurse to dump items in a folder. if path is None: path = '' path = os.path.join(path, obj.id) file = self._createFile(path, '.properties') self._writeProperties(obj, file) file.close() dumped = self._dumpObjects(obj.objectValues(), path) dumped.sort() # help diff out :) file = self._createFile(path, '.objects') for id, meta in dumped: file.write('%s:%s\n' % (id, meta)) file.close() def _dumpDTML(self, obj, path=None): # Dump obj (assumed to be a DTML Method/Document) to the # filesystem as a file, appending ".dtml" to the name. peer_id = obj.id() file = self._createFile(path, '%s.dtml' % peer_id) text = obj.raw if text[-1] != '\n': text = '%s\n' % text file.write(text) file.close() def _dumpDTMLMethod(self, obj, path=None): self._dumpDTML(obj, path) file = self._createFile(path, '%s.properties' % obj.id()) file.write('title:string=%s\n' % obj.title) file.close() def _dumpDTMLDocument(self, obj, path=None): # Dump properties of obj (assumed to be a DTML Document) to the # filesystem as a file, appending ".dtml" to the name. self._dumpDTML(obj, path) file = self._createFile(path, '%s.properties' % obj.id()) self._writeProperties(obj, file) file.close() def _dumpExternalMethod(self, obj, path=None): # Dump properties of obj (assumed to be an Externa Method) to the # filesystem as a file, appending ".py" to the name. file = self._createFile(path, '%s.properties' % obj.id) file.write('title:string=%s\n' % obj.title) file.write('module:string=%s\n' % obj._module) file.write('function:string=%s\n' % obj._function) file.close() def _dumpFileOrImage(self, obj, path=None): # Dump properties of obj (assumed to be an Externa Method) to the # filesystem as a file, appending ".py" to the name. file = self._createFile(path, '%s.properties' % obj.id()) file.write('title:string=%s\n' % obj.title) file.write('content_type:string=%s\n' % obj.content_type) file.write('precondition:string=%s\n' % obj.precondition) file.close() file = self._createFile(path, obj.id(), 'wb') data = obj.data if type(data) == type(''): file.write(data) else: while data is not None: file.write(data.data) data = data.next file.close() def _dumpPythonMethod(self, obj, path=None): # Dump properties of obj (assumed to be a Python Method) to the # filesystem as a file, appending ".py" to the name. body_lines = string.split(obj._body, '\n') body = string.join(body_lines, '\n ') text = "def %s(%s)\n\n %s" % (obj.id, obj._params, body) if text[-1] != '\n': text = '%s\n' % text file = self._createFile(path, '%s.py' % obj.id) file.write(text) file.close() file = self._createFile(path, '%s.properties' % obj.id) file.write('title:string=%s\n' % obj.title) file.close() def _dumpSQLMethod(self, obj, path=None): # Dump properties of obj (assumed to be a SQL Method) to the # filesystem as a file, appending ".sql" to the name. file = self._createFile(path, '%s.sql' % obj.id) text = "%s\n\n%s" % (obj.arguments_src, obj.src) if text[-1] != '\n': text = '%s\n' % text file.write(text) file.close() file = self._createFile(path, '%s.properties' % obj.id) file.write('title:string=%s\n' % obj.title) file.write('connection_id:string=%s\n' % obj.connection_id) file.write('max_rows_:int=%s\n' % obj.max_rows_) file.write('max_cache_:int=%s\n' % obj.max_cache_) file.write('cache_time_:int=%s\n' % obj.cache_time_) file.write('class_name_:string=%s\n' % obj.class_name_) file.write('class_file_:string=%s\n' % obj.class_file_) file.close() def _dumpZCatalog(self, obj, path=None): # Dump properties of obj (assumed to be a ZCatalog) to the # filesystem as a file, appending ".catalog" to the name. file = self._createFile(path, '%s.catalog' % obj.id) for brain in obj.searchResults(): file.write('%s\n' % obj.getpath(brain.data_record_id_)) file.close() file = self._createFile(path, '%s.properties' % obj.id) file.write('title:string=%s\n' % obj.title) file.write('vocab_id:string=%s\n' % obj.vocab_id) file.write('threshold:int=%s\n' % obj.threshold) file.close() file = self._createFile(path, '%s.indexes' % obj.id) for index in obj.index_objects(): file.write('%s:%s\n' % (index.id, index.meta_type)) file.close() file = self._createFile(path, '%s.metadata' % obj.id) for column in obj.schema(): file.write('%s\n' % column) file.close() _handlers = { 'DTML Method': _dumpDTMLMethod, 'DTML Document': _dumpDTMLDocument, 'Folder': _dumpFolder, 'External Method': _dumpExternalMethod, 'File': _dumpFileOrImage, 'Image': _dumpFileOrImage, 'Python Method': _dumpPythonMethod, 'Z SQL Method': _dumpSQLMethod, 'ZCatalog': _dumpZCatalog #, 'SQL DB Conn' : _dumpDBConn #, 'ZClass' : _dumpZClass #, 'Permission' : _dumpPermission #, 'Factory' : _dumpFactory #, 'Wizard' : _dumpWizard #, 'WizardPage' : _dumpWizardPage } def testDump(self, peer_path, path=None, REQUEST=None): """ Test dumping a single item. """ obj = self.aq_parent.restrictedTraverse(peer_path) self._dumpObject(obj) if REQUEST is not None: REQUEST['RESPONSE'].redirect(self.absolute_url() + '/editForm' + '?manage_tabs_message=%s+dumped.' % peer_path)
from OFS.SimpleItem import SimpleItem from Globals import HTMLFile, package_home import os, string _dtmldir = os.path.join(package_home(globals()), 'dtml') addDumperForm = HTMLFile('addDumper', _dtmldir) def addDumper(self, id, fspath=None, REQUEST=None): """ """ dumper = Dumper() dumper.id = id dumper._setFSPath(fspath) self._setObject(id, dumper) if REQUEST is not None: REQUEST['RESPONSE'].redirect('manage_main') class Dumper(SimpleItem): """ """ meta_type = 'Dumper' manage_options = ({ 'label': 'Edit', 'action': 'editForm' }, { 'label': 'Security',
class LDIFMethod(LDAPMethod): 'LDIF Method' meta_type = 'LDIF Method' manage_main = HTMLFile('editLdif', globals()) manage_options = ( { 'label': 'Edit', 'action': 'manage_main' }, { 'label': 'Test', 'action': 'manage_testForm' }, { 'label': 'Security', 'action': 'manage_access' }, ) __ac_permissions__ = ( ( 'View management screens', ( 'manage_tabs', 'manage_main', ), ), ('Change LDAP Methods', ('manage_edit', 'manage_testForm', 'manage_test')), ('Use LDAP Methods', ('__call__', ''), ('Anonymous', 'Manager')), ) #manage_testForm = HTMLFile("testLdifForm", globals()) def __init__(self, id, title, connection_id, basedn, arguments, ldif, **kw): """ init method """ self.id = id self.title = title self.connection_id = connection_id self.basedn = basedn self.arguments_src = self.arguments = arguments self._arg = parse(arguments) self.ldif = str(ldif) def manage_edit(self, title, connection_id, basedn, arguments, ldif, REQUEST=None, **kw): """ commit changes """ self.title = title self.connection_id = connection_id self.basedn = basedn self.arguments_src = self.arguments = arguments self._arg = parse(arguments) self.ldif = str(ldif) if REQUEST is not None: return MessageDialog( title='Edited', message='<strong>%s</strong> has been changed.' % self.id, action='./manage_main', ) def __call__(self, REQUEST=None, src__=0, tst__=0, **kw): """ call the object """ if REQUEST is None: if kw: REQUEST = kw else: if hasattr(self, 'REQUEST'): REQUEST = self.REQUEST else: REQUEST = {} c = self._connection().GetConnection() if not c: raise LDAPError('LDAP Connection not open') if hasattr(self, 'aq_parent'): p = self.aq_parent else: p = None argdata = self._argdata(REQUEST) #use our BaseQuery's magic. :) argdata['basedn'] = self.basedn # Also need the authenticated user. auth_user = REQUEST.get('AUTHENTICATED_USER', None) if auth_user is None: auth_user = getattr(self, 'REQUEST', None) if auth_user is not None: try: auth_user = auth_user.get('AUTHENTICATED_USER', None) except: auth_user = None if auth_user is not None: if getSecurityManager is None: # working in a pre-Zope 2.2.x instance from AccessControl.User import verify_watermark verify_watermark(auth_user) argdata['AUTHENTICATED_USER'] = auth_user ldif = Ldif(self.ldif) # make a FilterTemplate ldif.cook() if getSecurityManager is None: # working in a pre-Zope 2.2 instance ldif = apply(ldif, (p, argdata)) #apply the template else: # Working with the new security manager (Zope 2.2.x ++) security = getSecurityManager() security.addContext(self) try: ldif = apply(ldif, (p, ), argdata) # apply the template finally: security.removeContext(self) ldif = str(ldif) #ensure it's a string #LOG('ldif', 0, ldif) if src__: return ldif #return the rendered source ### Apply Query from cStringIO import StringIO file = StringIO(ldif) l = ERP5LDIFRecordList(file) l.parse() res = l.all_records def delete(c, dn): try: c.delete_s(dn) except ldap.NO_SUCH_OBJECT: pass except: LOG('ldif', INFO, ldif) raise def add(c, dn, mod_list): try: c.add_s(dn, mod_list) except ldap.ALREADY_EXISTS: pass except: LOG('ldif', INFO, ldif) raise for record in res: dn = record[0] entry = record[1] if type(entry) == type({}): authorized_modify_key = [ key for key in entry.keys() if key in CHANGE_TYPES ] if len(authorized_modify_key): for key in authorized_modify_key: tuple_list = entry[key] if key == 'delete': try: delete(c, dn) except ldap.SERVER_DOWN: c = self._connection().getForcedConnection() delete(c, dn) else: for mod_tuple in tuple_list: c.modify_s(dn, mod_tuple) else: mod_list = modlist.addModlist(entry) try: add(c, dn, mod_list) except ldap.SERVER_DOWN: c = self._connection().getForcedConnection() add(c, dn, mod_list) else: LOG('LDIFMethod Type unknow', INFO, '') return res
class LDAPMethod( Aqueduct.BaseQuery, Acquisition.Implicit, Globals.Persistent, AccessControl.Role.RoleManager, OFS.SimpleItem.Item, ): 'LDAP Method' meta_type = 'LDAP Method' manage_main = HTMLFile('edit', globals()) manage_options = ( { 'label': 'Edit', 'action': 'manage_main' }, { 'label': 'Test', 'action': 'manage_testForm' }, { 'label': 'Security', 'action': 'manage_access' }, ) __ac_permissions__ = ( ( 'View management screens', ( 'manage_tabs', 'manage_main', ), ), ('Change LDAP Methods', ('manage_edit', 'manage_testForm', 'manage_test')), ('Use LDAP Methods', ('__call__', ''), ('Anonymous', 'Manager')), ) #manage_testForm = HTMLFile("testForm", globals()) def manage_testForm(self, REQUEST): " " input_src = default_input_form(self.title_or_id(), self._arg, 'manage_test', '<!--#var manage_tabs-->') return DocumentTemplate.HTML(input_src)(self, REQUEST, HTTP_REFERER='') def __init__(self, id, title, connection_id, scope, basedn, arguments, filters): """ init method """ self.id = id self.title = title self.connection_id = connection_id self._scope = _ldapScopes[scope] self.scope = scope self.basedn = basedn self.arguments_src = self.arguments = arguments self._arg = parse(arguments) self.filters = filters def recomputeBaseDN(self): ' recompute base DN based on connection ' cdn = self._connection().dn if self.basedn: self.basedn = '%s, %s' % (self.basedn, cdn) else: self.basedn = cdn return self.basedn def manage_edit(self, title, connection_id, scope, basedn, arguments, filters, REQUEST=None): """ commit changes """ self.title = title self.connection_id = connection_id self._scope = _ldapScopes[scope] self.scope = scope self.basedn = basedn self.arguments_src = self.arguments = arguments self._arg = parse(arguments) self.filters = filters if REQUEST is not None: return MessageDialog( title='Edited', message='<strong>%s</strong> has been changed.' % self.id, action='./manage_main', ) def cleanse(self, s): import string # kill line breaks &c. s = string.join(string.split(s)) return s def _connection(self): ' return actual ZLDAP Connection Object ' return getattr(self, self.connection_id, None) def _getConn(self): return self._connection().GetConnection() # Hacky, Hacky GetConnection = _getConn def manage_test(self, REQUEST): """ do the test query """ src = "Could not render the filter template!" res = () t = v = tb = None try: try: src = self(REQUEST, src__=1) res = self(REQUEST, tst__=1) r = self.prettyResults(res) except: t, v, tb = sys.exc_info() r = '<strong>Error, <em>%s</em>:</strong> %s' % (t, v) report = DocumentTemplate.HTML( '<html><body bgcolor="#ffffff">\n' '<!--#var manage_tabs-->\n<hr>%s\n\n' '<hr><strong>Filter used:</strong><br>\n<pre>\n%s\n</pre>\n<hr>\n' '</body></html>' % (r, src)) report = apply(report, (self, REQUEST), {self.id: res}) if tb is not None: self.raise_standardErrorMessage(None, REQUEST, t, v, tb, None, report) return report finally: tb = None def prettyResults(self, res): s = "" if not res or not len(res): s = "no results" else: for dn, attrs in res: s = s + ('<ul><li><b>DN: %s</b></li>\n<ul>' % dn) s = s + str(pretty_results(attrs=attrs.items())) s = s + '</ul></ul>' return s def __call__(self, REQUEST=None, src__=0, tst__=0, **kw): """ call the object """ if REQUEST is None: if kw: REQUEST = kw else: if getattr(self, 'REQUEST', None) is not None: REQUEST = self.REQUEST else: REQUEST = {} c = self._getConn() if not c: raise LDAPError('LDAP Connection not open') if getattr(self, 'aq_parent', None) is not None: p = self.aq_parent else: p = None argdata = self._argdata(REQUEST) #use our BaseQuery's magic. :) # Also need the authenticated user. auth_user = REQUEST.get('AUTHENTICATED_USER', None) if auth_user is None: auth_user = getattr(self, 'REQUEST', None) if auth_user is not None: try: auth_user = auth_user.get('AUTHENTICATED_USER', None) except: auth_user = None if auth_user is not None: if getSecurityManager is None: # working in a pre-Zope 2.2.x instance from AccessControl.User import verify_watermark verify_watermark(auth_user) argdata['AUTHENTICATED_USER'] = auth_user f = Filter(self.filters) # make a FilterTemplate f.cook() if getSecurityManager is None: # working in a pre-Zope 2.2 instance f = apply(f, (p, argdata)) #apply the template else: # Working with the new security manager (Zope 2.2.x ++) security = getSecurityManager() security.addContext(self) try: f = apply(f, (p, ), argdata) # apply the template finally: security.removeContext(self) f = str(f) #ensure it's a string if src__: return f #return the rendered source f = self.cleanse(f) ### run the search res = c.search_s(self.basedn, self._scope, f) if tst__: return res #return test-friendly data ### instantiate Entry objects based on results l = [] #list of entries to return conn = self._connection() #ZLDAPConnection Entry = conn._EntryFactory() for dn, attrdict in res: e = Entry(dn, attrdict, conn).__of__(self) l.append(e) return l
if (hasattr(o, '_isAnLDAPConnection') and o._isAnLDAPConnection() and hasattr(o, 'id')): id = o.id if type(id) is not StringType: id = id() if not ids.has_key(id): if hasattr(o, 'title_and_id'): o = o.title_and_id() else: o = id ids[id] = id if hasattr(self, 'aq_parent'): self = self.aq_parent else: self = None ids = map(lambda item: (item[1], item[0]), ids.items()) ids.sort() return ids manage_addZLDAPMethodForm = HTMLFile('add', globals()) def manage_addZLDAPMethod(self, id, title, connection_id, scope, basedn, filters, arguments, getfromconnection=0, REQUEST=None, submit=None): """Add an LDAP Method """ l = LDAPMethod(id, title, connection_id, scope, basedn, arguments, filters)
class ExtImage(ExtFile): """ The ExtImage-Product works like the Zope Image-product, but stores the uploaded image externally in a repository-directory. It can create a preview of the image (requires PIL).""" if IDAVAware is not None: interface.implements(IExtImage, IDAVAware) else: interface.implements(IExtImage) # BBB __implements__ = (WriteLockInterface, ) security = ClassSecurityInfo() # what do people think they're adding? meta_type = 'ExtImage' # default,min,max-sizes for the preview image _image_size = {'default': 256, 'min': 1, 'max': 999} # store maxx and maxy prev_maxx = _image_size['default'] prev_maxy = _image_size['default'] ################################ # Init method # ################################ def __init__(self, id, title='', descr='', permission_check=0, redirect_default_view=0): """ Initialize a new instance of ExtImage """ super(ExtImage, self).__init__(id, title, descr, permission_check, redirect_default_view) self.prev_filename = [] self.prev_content_type = '' self.prev_ratio = 1 self.has_preview = 0 ################################ # Public methods # ################################ def __str__(self): return self.tag() security.declareProtected(ViewPermission, 'tag') def tag(self, preview=0, icon=0, height=None, width=None, alt=None, scale=0, xscale=0, yscale=0, border='0', REQUEST=None, **args): """ Generate an HTML IMG tag for this image, with customization. Arguments to self.tag() can be any valid attributes of an IMG tag. 'src' will always be an absolute pathname, to prevent redundant downloading of images. Defaults are applied intelligently for 'height', 'width', and 'alt'. If specified, the 'scale', 'xscale', and 'yscale' keyword arguments will be used to automatically adjust the output height and width values of the image tag. Adopted and adapted from OFS/Image.py """ if not self.is_webviewable(): preview = 1 if not self._access_permitted(): preview = 1 if preview and not self.has_preview: icon = 1 if icon: url = self._static_url(icon=1) img_width, img_height = (32, 32) elif preview: url = self._static_url(preview=1) img_width, img_height = self._getImageSize(self.prev_filename) else: url = self._static_url() img_width, img_height = self._getImageSize(self.filename) height = height or img_height width = width or img_width # Auto-scaling support xdelta = xscale or scale ydelta = yscale or scale if xdelta and width != None: width = str(int(int(width) * xdelta)) if ydelta and height != None: height = str(int(int(height) * ydelta)) if alt is None: alt = self.title or '' strg = '<img src="%s" border="%s" alt="%s"' % \ (url, border, alt) if height: strg = '%s height="%s"' % (strg, height) if width: strg = '%s width="%s"' % (strg, width) for key in args.keys(): value = args.get(key) strg = '%s %s="%s"' % (strg, key, value) strg = "%s />" % (strg) return strg security.declareProtected(ViewPermission, 'preview') def preview(self): """ Return a preview of the image """ raise Redirect(self._static_url(preview=1)) security.declareProtected(ViewPermission, 'preview_tag') def preview_tag(self): """ Generates the HTML IMG tag for the preview image """ return self.tag(preview=1) security.declareProtected(ViewPermission, 'preview_html') def preview_html(self): """ Same as preview_tag """ return self.preview_tag() security.declareProtected(ViewPermission, 'preview_link') def preview_link(self, text='', **args): """ Return an HTML link tag for the preview image. Assumes all arguments are properly quoted. """ if not text: text = html_quote(self.title_or_id()) return self._link(self._static_url(preview=1), text, **args) security.declareProtected(ViewPermission, 'thumbnail_tag') def thumbnail_tag(self, size=180): """ Returns the HTML image tag for a thumbnail view of this image. Used by the ZMI. """ # Try hard to return something useful even in the face of breakage size = max(0, size) if self.has_preview: if self._get_fsname(self.prev_filename): width, height = self._getImageSize(self.prev_filename) if width > size or height > size: return self.tag(preview=1, scale=float(size) / max(width, height)) else: return self.tag(preview=1) else: # tag() is too helpful here... return '<img src="%s?preview=1" border="0" alt="" height="32" width="32" />' % \ (self.absolute_url(),) else: if self.is_webviewable(): width, height = self._getImageSize(self.filename) if width > size or height > size: return self.tag(scale=float(size) / max(width, height)) else: return self.tag() else: if self._get_fsname(self.filename): return self.tag(icon=1) else: # tag() is too helpful here... return '<img src="%s" border="0" alt="" height="32" width="32" />' % \ (self.absolute_url(),) security.declareProtected(ViewPermission, 'is_broken') def is_broken(self): """ Check if external file exists and return true (1) or false (0) """ if self.has_preview and self.filename != self.prev_filename: if not self._get_fsname(self.prev_filename): return 1 return super(ExtImage, self).is_broken() security.declareProtected(ViewPermission, 'is_webviewable') def is_webviewable(self): """ Return 1 for GIF, JPEG, and PNG images, otherwise return 0 """ format = self.format() if format == 'JPEG' or format == 'GIF' or format == 'PNG': return 1 else: return 0 security.declareProtected(ViewPermission, 'get_prev_size') def get_prev_size(self): """ Returns the size of the preview file """ fn = self._get_fsname(self.prev_filename) if fn: return os.stat(fn)[6] return 0 security.declareProtected(ViewPermission, 'prev_rawsize') def prev_rawsize(self): """ Same as get_prev_size """ return self.get_prev_size() security.declareProtected(ViewPermission, 'prev_size') def prev_size(self): """ Returns a formatted stringified version of the preview size """ return self._bytetostring(self.get_prev_size()) security.declareProtected(ViewPermission, 'width') def width(self): """ Pixel width of the image """ return self._getImageSize(self.filename)[0] security.declareProtected(ViewPermission, 'height') def height(self): """ Pixel height of the image """ return self._getImageSize(self.filename)[1] security.declareProtected(ViewPermission, 'prev_width') def prev_width(self): """ Pixel width of the preview """ return self._getImageSize(self.prev_filename)[0] security.declareProtected(ViewPermission, 'prev_height') def prev_height(self): """ Pixel height of the preview """ return self._getImageSize(self.prev_filename)[1] security.declareProtected(ViewPermission, 'format') def format(self): """ Get the PIL file format of the image """ filename = self._get_fsname(self.filename) try: from PIL import Image im = Image.open(filename) return im.format except: return 'unknown' security.declareProtected(AccessPermission, 'get_prev_filename') def get_prev_filename(self): """ Returns the preview file name for display """ return self._fsname(self.prev_filename) ################################ # Protected management methods # ################################ # Management Interface security.declareProtected(AccessPermission, 'manage_main') manage_main = HTMLFile('www/extImageEdit', globals()) security.declareProtected(ChangePermission, 'manage_del_prev') def manage_del_prev(self, REQUEST=None): """ Delete the Preview Image """ if self.has_preview and self.filename != self.prev_filename: self._delete(self.prev_filename) self.prev_content_type = '' self.has_preview = 0 self.ZCacheable_invalidate() if REQUEST is not None: return self.manage_main(self, REQUEST, manage_tabs_message='Preview deleted.') security.declareProtected(ChangePermission, 'manage_create_prev') def manage_create_prev(self, maxx=0, maxy=0, ratio=0, REQUEST=None): """ Create a preview Image """ maxx, maxy = self._formatDimensions(maxx, maxy) if maxx != 0 and maxy != 0: self._register() # Register with TM try: new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg') self._createPreview(self.filename, new_fn, maxx, maxy, ratio) finally: self._dir__unlock() if REQUEST is None: return self.has_preview else: if self.has_preview: return self.manage_main(self, REQUEST, manage_tabs_message='Preview created.') elif maxx == '0' and maxy == '0': return MessageDialog( title='Attention', message="You must enter a value > 0", action='./manage_main', ) else: return MessageDialog( title='Warning', message="An error occurred while generating the preview.", action='./manage_main', ) # File upload Interface security.declareProtected(AccessPermission, 'manage_uploadForm') manage_uploadForm = HTMLFile('www/extImageUpload', globals()) security.declareProtected(ChangePermission, 'manage_upload') def manage_upload(self, file='', content_type='', is_preview=0, create_prev=NO_PREVIEW, maxx='', maxy='', ratio=0, REQUEST=None): """ Upload image from file handle or string buffer """ if self.wl_isLocked(): raise ResourceLockedError("File is locked via WebDAV") if isinstance(file, str): temp_file = TemporaryFile() temp_file.write(file) temp_file.seek(0) else: temp_file = file return self.manage_file_upload(temp_file, content_type, is_preview, create_prev, maxx, maxy, ratio, REQUEST) security.declareProtected(ChangePermission, 'manage_file_upload') def manage_file_upload(self, file='', content_type='', is_preview=0, create_prev=NO_PREVIEW, maxx='', maxy='', ratio=0, REQUEST=None): """ Upload image from file handle or local directory """ if self.wl_isLocked(): raise ResourceLockedError("File is locked via WebDAV") if is_preview: if isinstance(file, str): file = open(file, 'rb') maxx, maxy = self._formatDimensions(maxx, maxy) if create_prev == UPLOAD_RESIZE and maxx != 0 and maxy != 0: self._register() # Register with TM try: new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg') self._update_data(file, self._temp_fsname(new_fn)) finally: self._dir__unlock() self._createPreview(new_fn, new_fn, maxx, maxy, ratio) else: if content_type: file = HTTPUpload(file, content_type) content_type = self._get_content_type(file, file.read(100), self.id, self.prev_content_type) file.seek(0) self._register() # Register with TM try: backup = REPOSITORY_EXTENSIONS in (MIMETYPE_APPEND, MIMETYPE_REPLACE) and \ self.prev_filename and self.prev_content_type != content_type new_fn = self._get_ufn(self.prev_filename, content_type=content_type, backup=backup) self._update_data(file, self._temp_fsname(new_fn)) finally: self._dir__unlock() self.prev_filename = new_fn self.prev_content_type = content_type self._initPreview() else: super(ExtImage, self).manage_file_upload(file, content_type) if create_prev == GENERATE: maxx, maxy = self._formatDimensions(maxx, maxy) if maxx != 0 and maxy != 0: self._register() # Register with TM try: new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg') self._createPreview(self.filename, new_fn, maxx, maxy, ratio) finally: self._dir__unlock() if REQUEST is not None: return self.manage_main(self, REQUEST, manage_tabs_message='Upload complete.') security.declareProtected(ChangePermission, 'manage_http_upload') def manage_http_upload(self, url, is_preview=0, REQUEST=None): """ Upload image from http-server """ if self.wl_isLocked(): raise ResourceLockedError("File is locked via WebDAV") if is_preview: url = urllib.quote(url, '/:') file = urllib.urlopen(url) file = HTTPUpload(file) content_type = self._get_content_type(file, file.read(100), self.id, self.prev_content_type) file.seek(0) self._register() # Register with TM try: backup = REPOSITORY_EXTENSIONS in (MIMETYPE_APPEND, MIMETYPE_REPLACE) and \ self.prev_filename and self.prev_content_type != content_type new_fn = self._get_ufn(self.prev_filename, content_type=content_type, backup=backup) self._update_data(file, self._temp_fsname(new_fn)) finally: self._dir__unlock() self.prev_filename = new_fn self.prev_content_type = content_type self._initPreview() else: super(ExtImage, self).manage_http_upload(url) if REQUEST is not None: return self.manage_main(self, REQUEST, manage_tabs_message='Upload complete.') security.declareProtected(ChangePermission, 'PUT') def PUT(self, REQUEST, RESPONSE): """ Handle HTTP PUT requests """ RESPONSE = super(ExtImage, self).PUT(REQUEST, RESPONSE) if self.has_preview: maxx, maxy = self._formatDimensions(self.prev_maxx, self.prev_maxy) self._register() # Register with TM try: new_fn = self._get_ufn(self.prev_filename, content_type='image/jpeg') self._createPreview(self.filename, new_fn, maxx, maxy, self.prev_ratio) finally: self._dir__unlock() return RESPONSE ################################ # Private methods # ################################ def _getImageSize(self, filename): """ Return width, height tuple using PIL """ filename = self._get_fsname(filename) try: from PIL import Image im = Image.open(filename) return im.size[0], im.size[1] except: return 0, 0 def _createPreview(self, from_filename, to_filename, maxx, maxy, ratio): """ Generate a preview using PIL """ try: from PIL import Image except ImportError: pass else: imfile = self._get_fsname(from_filename) if imfile: im = Image.open(imfile) if im.mode != 'RGB': im = im.convert('RGB') filter = Image.BICUBIC if hasattr(Image, 'ANTIALIAS'): # PIL 1.1.3 filter = Image.ANTIALIAS if ratio: # keep aspect-ratio im.thumbnail((maxx, maxy), filter) else: # distort to fixed size im = im.resize((maxx, maxy), filter) umask = os.umask(REPOSITORY_UMASK) outfile = self._temp_fsname(to_filename) try: im.save(outfile, 'JPEG', quality=85) except: os.umask(umask) if isfile(outfile): try: os.remove(outfile) except OSError: logger.error('_createPreview', exc_info=True) raise else: os.umask(umask) self.prev_content_type = 'image/jpeg' self.prev_filename = to_filename self.prev_maxx = maxx self.prev_maxy = maxy self.prev_ratio = ratio self._initPreview() def _initPreview(self): """ Verify the preview """ self.ZCacheable_invalidate() prev_width, prev_height = self._getImageSize(self.prev_filename) if prev_width <= 0 or prev_height <= 0: self.has_preview = 0 else: self.has_preview = 1 def _formatDimensions(self, maxx, maxy): """ Make sure, the dimensions are valid int's """ if isinstance(maxx, str): try: maxx = int(maxx) except ValueError: maxx = self._image_size['default'] if isinstance(maxy, str): try: maxy = int(maxy) except ValueError: maxy = self._image_size['default'] if maxx != 0 and maxy != 0: if maxx < self._image_size['min']: maxx = self._image_size['min'] elif maxx > self._image_size['max']: maxx = self._image_size['max'] if maxy < self._image_size['min']: maxy = self._image_size['min'] elif maxy > self._image_size['max']: maxy = self._image_size['max'] return maxx, maxy def _get_content_type(self, file, body, id, content_type=None): """ Determine the mime-type """ ct, w, h = getImageInfo(body) if ct: content_type = ct else: content_type = super(ExtImage, self)._get_content_type( file, body, id, content_type) return content_type def _afterUpdate(self): """ Called whenever the image data has been updated. Fires an ExtImageUpdatedEvent. """ self.ZCacheable_invalidate() event.notify(ExtImageUpdatedEvent(self)) ################################ # Transaction manager methods # ################################ def _finish(self): """ Commits the temporary file """ if self.prev_filename and self.filename != self.prev_filename: tmp_fn = self._temp_fsname(self.prev_filename) if _debug: logger.info('finishing %s' % tmp_fn) if isfile(tmp_fn): if _debug: logger.info('isfile %s' % tmp_fn) fn = self._fsname(self.prev_filename) if isfile(fn): try: os.remove(fn) except OSError: logger.error('_finish', exc_info=True) try: os.rename(tmp_fn, fn) except OSError: logger.error('_finish', exc_info=True) super(ExtImage, self)._finish() def _abort(self): """ Deletes the temporary file """ if self.prev_filename and self.filename != self.prev_filename: tmp_fn = self._temp_fsname(self.prev_filename) if _debug: logger.info('aborting %s' % tmp_fn) if isfile(tmp_fn): if _debug: logger.info('isfile %s' % tmp_fn) try: os.remove(tmp_fn) except OSError: logger.error('_abort', exc_info=True) super(ExtImage, self)._abort()
""" Converts Subject string into a List for content filter view. """ for sub in obj.Subject(): if sub in self.filterSubject: return 1 return 0 def __call__(self, content): for predicate in self.predicates: try: if not predicate(content): return 0 except: # XXX return 0 return 1 def __str__(self): """ """ return "Subject: %s; Type: %s" % (self.filterSubject, self.filterType) manage_addPortalFolder = PortalFolder.manage_addPortalFolder manage_addPortalFolderForm = HTMLFile('folderAdd', globals()) Globals.InitializeClass(PortalFolder)
# they are, even to log them. try: del self.resp.unauthorized except: pass try: del self.resp._unauthorized except: pass try: del self.resp except: pass manage_addCCForm = HTMLFile('dtml/addCC', globals()) manage_addCCForm.__name__ = 'addCC' def _create_forms(ob): ''' Create default forms inside ob ''' import os from OFS.DTMLMethod import addDTMLMethod dtmldir = os.path.join(os.path.dirname(__file__), 'dtml') for fn in ('index_html', 'logged_in', 'logged_out', 'login_form', 'standard_login_footer', 'standard_login_header'): filename = os.path.join(dtmldir, fn + '.dtml') f = open(filename, 'rt') try: data = f.read() finally:
class Connection(Shared.DC.ZRDB.Connection.Connection): """ZPsycopg Connection.""" _isAnSQLConnection = 1 id = 'Psycopg2_database_connection' database_type = 'Psycopg2' meta_type = title = 'Z Psycopg 2 Database Connection' icon = 'misc_/conn' def __init__(self, id, title, connection_string, zdatetime, check=None, tilevel=2, encoding='UTF-8'): self.zdatetime = zdatetime self.id = str(id) self.edit(title, connection_string, zdatetime, check=check, tilevel=tilevel, encoding=encoding) def factory(self): return DB ## connection parameters editing ## def edit(self, title, connection_string, zdatetime, check=None, tilevel=2, encoding='UTF-8'): self.title = title self.connection_string = connection_string self.zdatetime = zdatetime self.tilevel = tilevel self.encoding = encoding if check: self.connect(self.connection_string) manage_properties = HTMLFile('dtml/edit', globals()) def manage_edit(self, title, connection_string, zdatetime=None, check=None, tilevel=2, encoding='UTF-8', REQUEST=None): """Edit the DB connection.""" self.edit(title, connection_string, zdatetime, check=check, tilevel=tilevel, encoding=encoding) if REQUEST is not None: msg = "Connection edited." return self.manage_main(self, REQUEST, manage_tabs_message=msg) def connect(self, s): try: self._v_database_connection.close() except: pass # check psycopg version and raise exception if does not match if psycopg2.__version__.split(' ')[0] not in ALLOWED_PSYCOPG_VERSIONS: raise ImportError("psycopg version mismatch (imported %s)" % psycopg2.__version__) self._v_connected = '' dbf = self.factory() # TODO: let the psycopg exception propagate, or not? self._v_database_connection = dbf(self.connection_string, self.tilevel, self.get_type_casts(), self.encoding) self._v_database_connection.open() self._v_connected = DateTime() return self def get_type_casts(self): # note that in both cases order *is* important if self.zdatetime: return ZDATETIME, ZDATE, ZTIME else: return DATETIME, DATE, TIME ## browsing and table/column management ## manage_options = Shared.DC.ZRDB.Connection.Connection.manage_options # + ( # {'label': 'Browse', 'action':'manage_browse'},) #manage_tables = HTMLFile('dtml/tables', globals()) #manage_browse = HTMLFile('dtml/browse', globals()) info = None def table_info(self): return self._v_database_connection.table_info() def __getitem__(self, name): if name == 'tableNamed': if not hasattr(self, '_v_tables'): self.tpValues() return self._v_tables.__of__(self) raise KeyError, name def tpValues(self): res = [] conn = self._v_database_connection for d in conn.tables(rdb=0): try: name = d['TABLE_NAME'] b = TableBrowser() b.__name__ = name b._d = d b._c = c try: b.icon = table_icons[d['TABLE_TYPE']] except: pass r.append(b) except: pass return res
except ImportError: # Zope < 2.9. If PIL's installed with a .pth file, we're probably # hosed. from ImageFile import ImageFile # import psycopg and functions/singletons needed for date/time conversions import psycopg2 from psycopg2 import NUMBER, STRING, ROWID, DATETIME from psycopg2.extensions import INTEGER, LONGINTEGER, FLOAT, BOOLEAN, DATE from psycopg2.extensions import TIME, INTERVAL from psycopg2.extensions import new_type, register_type # add a new connection to a folder manage_addZPsycopgConnectionForm = HTMLFile('dtml/add', globals()) def manage_addZPsycopgConnection(self, id, title, connection_string, zdatetime=None, tilevel=2, encoding='', check=None, REQUEST=None): """Add a DB connection to a folder.""" self._setObject( id, Connection(id, title, connection_string, zdatetime, check, tilevel,
from Globals import InitializeClass, HTMLFile from OFS.SimpleItem import Item from OFS.PropertyManager import PropertyManager from Acquisition import Explicit, Implicit from Persistence import Persistent from AccessControl import ClassSecurityInfo from AccessControl import ModuleSecurityInfo modulesecurity = ModuleSecurityInfo() import roundup.instance from roundup.cgi import client modulesecurity.declareProtected('View management screens', 'manage_addZRoundupForm') manage_addZRoundupForm = HTMLFile('dtml/manage_addZRoundupForm', globals()) modulesecurity.declareProtected('Add Z Roundups', 'manage_addZRoundup') def manage_addZRoundup(self, id, instance_home, REQUEST): """Add a ZRoundup product """ # validate the instance_home roundup.instance.open(instance_home) self._setObject(id, ZRoundup(id, instance_home)) return self.manage_main(self, REQUEST) class RequestWrapper: '''Make the Zope RESPONSE look like a BaseHTTPServer '''
class SyndicationTool(UniqueObject, SimpleItem): """ The syndication tool manages the site-wide policy for syndication of folder content as RSS. """ implements(ISyndicationTool) __implements__ = SimpleItem.__implements__ id = 'portal_syndication' meta_type = 'Default Syndication Tool' security = ClassSecurityInfo() #Default Sitewide Values isAllowed = 0 syUpdatePeriod = 'daily' syUpdateFrequency = 1 syUpdateBase = DateTime() max_items = 15 #ZMI Methods manage_options = (({ 'label': 'Overview', 'action': 'overview', 'help': ('CMFDefault', 'Syndication-Tool_Overview.stx') }, { 'label': 'Properties', 'action': 'propertiesForm', 'help': ('CMFDefault', 'Syndication-Tool_Properties.stx') }, { 'label': 'Policies', 'action': 'policiesForm', 'help': ('CMFDefault', 'Syndication-Tool_Policies.stx') }, { 'label': 'Reports', 'action': 'reportForm', 'help': ('CMFDefault', 'Syndication-Tool_Reporting.stx') })) security.declareProtected(ManagePortal, 'overview') overview = HTMLFile('synOverview', _dtmldir) security.declareProtected(ManagePortal, 'propertiesForm') propertiesForm = HTMLFile('synProps', _dtmldir) security.declareProtected(ManagePortal, 'policiesForm') policiesForm = HTMLFile('synPolicies', _dtmldir) security.declareProtected(ManagePortal, 'reportForm') reportForm = HTMLFile('synReports', _dtmldir) security.declareProtected(ManagePortal, 'editProperties') def editProperties(self, updatePeriod=None, updateFrequency=None, updateBase=None, isAllowed=None, max_items=None, REQUEST=None): """ Edit the properties for the SystemWide defaults on the SyndicationTool. """ if isAllowed is not None: self.isAllowed = isAllowed if updatePeriod is not None: self.syUpdatePeriod = updatePeriod else: try: del self.syUpdatePeriod except (AttributeError, KeyError): pass if updateFrequency is not None: self.syUpdateFrequency = int(updateFrequency) else: try: del self.syUpdateFrequency except (AttributeError, KeyError): pass if updateBase is not None: if type(updateBase) is type(''): updateBase = DateTime(updateBase) self.syUpdateBase = updateBase else: try: del self.syUpdateBase except (AttributeError, KeyError): pass if max_items is not None: self.max_items = int(max_items) else: try: del self.max_items except (AttributeError, KeyError): pass if REQUEST is not None: REQUEST['RESPONSE'].redirect(self.absolute_url() + '/propertiesForm' + '?manage_tabs_message=Tool+Updated.') security.declarePublic('editSyInformationProperties') def editSyInformationProperties(self, obj, updatePeriod=None, updateFrequency=None, updateBase=None, max_items=None, REQUEST=None): """ Edit syndication properties for the obj being passed in. These are held on the syndication_information object. Not Sitewide Properties. """ if not _checkPermission(ManageProperties, obj): raise AccessControl_Unauthorized syInfo = getattr(obj, 'syndication_information', None) if syInfo is None: raise 'Syndication is Disabled' if updatePeriod is not None: syInfo.syUpdatePeriod = updatePeriod else: syInfo.syUpdatePeriod = self.syUpdatePeriod if updateFrequency is not None: syInfo.syUpdateFrequency = int(updateFrequency) else: syInfo.syUpdateFrequency = self.syUpdateFrequency if updateBase is not None: if type(updateBase) is type(''): updateBase = DateTime(updateBase) syInfo.syUpdateBase = updateBase else: syInfo.syUpdateBase = self.syUpdateBase if max_items is not None: syInfo.max_items = int(max_items) else: syInfo.max_items = self.max_items security.declarePublic('enableSyndication') def enableSyndication(self, obj): """ Enable syndication for the obj """ if not self.isSiteSyndicationAllowed(): raise 'Syndication is Disabled' if hasattr(aq_base(obj), 'syndication_information'): raise 'Syndication Information Exists' syInfo = SyndicationInformation() obj._setObject('syndication_information', syInfo) syInfo = obj._getOb('syndication_information') syInfo.syUpdatePeriod = self.syUpdatePeriod syInfo.syUpdateFrequency = self.syUpdateFrequency syInfo.syUpdateBase = self.syUpdateBase syInfo.max_items = self.max_items syInfo.description = "Channel Description" security.declarePublic('disableSyndication') def disableSyndication(self, obj): """ Disable syndication for the obj; and remove it. """ syInfo = getattr(obj, 'syndication_information', None) if syInfo is None: raise 'This object does not have Syndication Information' obj._delObject('syndication_information') security.declarePublic('getSyndicatableContent') def getSyndicatableContent(self, obj): """ An interface for allowing folderish items to implement an equivalent of PortalFolderBase.contentValues() """ if hasattr(obj, 'synContentValues'): values = obj.synContentValues() else: values = PortalFolderBase.contentValues(obj) return values security.declarePublic('buildUpdatePeriods') def buildUpdatePeriods(self): """ Return a list of possible update periods for the xmlns: sy """ updatePeriods = (('hourly', 'Hourly'), ('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly'), ('yearly', 'Yearly')) return updatePeriods security.declarePublic('isSiteSyndicationAllowed') def isSiteSyndicationAllowed(self): """ Return sitewide syndication policy """ return self.isAllowed security.declarePublic('isSyndicationAllowed') def isSyndicationAllowed(self, obj=None): """ Check whether syndication is enabled for the site. This provides for extending the method to check for whether a particular obj is enabled, allowing for turning on only specific folders for syndication. """ syInfo = getattr(aq_base(obj), 'syndication_information', None) if syInfo is None: return 0 else: return self.isSiteSyndicationAllowed() security.declarePublic('getUpdatePeriod') def getUpdatePeriod(self, obj=None): """ Return the update period for the RSS syn namespace. This is either on the object being passed or the portal_syndication tool (if a sitewide value or default is set) NOTE: Need to add checks for sitewide policies!!! """ if not self.isSiteSyndicationAllowed(): raise 'Syndication is Not Allowed' if obj is None: return self.syUpdatePeriod syInfo = getattr(obj, 'syndication_information', None) if syInfo is not None: return syInfo.syUpdatePeriod else: return 'Syndication is Not Allowed' security.declarePublic('getUpdateFrequency') def getUpdateFrequency(self, obj=None): """ Return the update frequency (as a positive integer) for the syn namespace. This is either on the object being pass or the portal_syndication tool (if a sitewide value or default is set). Note: Need to add checks for sitewide policies!!! """ if not self.isSiteSyndicationAllowed(): raise 'Syndication is not Allowed' if obj is None: return self.syUpdateFrequency syInfo = getattr(obj, 'syndication_information', None) if syInfo is not None: return syInfo.syUpdateFrequency else: return 'Syndication is not Allowed' security.declarePublic('getUpdateBase') def getUpdateBase(self, obj=None): """ Return the base date to be used with the update frequency and the update period to calculate a publishing schedule. Note: I'm not sure what's best here, creation date, last modified date (of the folder being syndicated) or some arbitrary date. For now, I'm going to build a updateBase time from zopetime and reformat it to meet the W3CDTF. Additionally, sitewide policy checks might have a place here... """ if not self.isSiteSyndicationAllowed(): raise 'Syndication is not Allowed' if obj is None: when = self.syUpdateBase return when.ISO() syInfo = getattr(obj, 'syndication_information', None) if syInfo is not None: when = syInfo.syUpdateBase return when.ISO() else: return 'Syndication is not Allowed' security.declarePublic('getHTML4UpdateBase') def getHTML4UpdateBase(self, obj=None): """ Return HTML4 formated UpdateBase DateTime """ if not self.isSiteSyndicationAllowed(): raise 'Syndication is not Allowed' if obj is None: when = self.syUpdateBase return when.HTML4() syInfo = getattr(obj, 'syndication_information', None) if syInfo is not None: when = syInfo.syUpdateBase return when.HTML4() else: return 'Syndication is not Allowed' def getMaxItems(self, obj=None): """ Return the max_items to be displayed in the syndication """ if not self.isSiteSyndicationAllowed(): raise 'Syndication is not Allowed' if obj is None: return self.max_items syInfo = getattr(obj, 'syndication_information', None) if syInfo is not None: return syInfo.max_items else: return 'Syndication is not Allowed'
class DiscussionItem(Document, DiscussionResponse, DefaultDublinCoreImpl): """ This is the PortalContent object for content which is a response to other content. """ meta_type = 'Discussion Item' allow_discussion = 1 __ac_permissions__ = ( ('Change Discussion Items', ('edit', ), ('Owner', )), ('View', ('', 'absolute_url', 'getReplies', 'view')), ) view = HTMLFile('dtml/discussionView', globals()) index_html = view editForm = HTMLFile('dtml/discussionEdit', globals()) # Replies should default to published review_state = 'published' def absolute_url(self, relative=0): portal_url = getToolByName(self, 'portal_url') container = self.aq_inner.aq_parent content_item = container.aq_inner.aq_parent parent_rel_url = portal_url.getRelativeUrl(content_item) if relative: return parent_rel_url + '/talkback/' + str(self.id) else: return portal_url() + '/' + parent_rel_url + '/talkback/' + str( self.id) def getPhysicalPath(self): """ Needs to be overridden here because the standard implementation doesn't fit my needs in case i am stored in a DiscussionItemContainer """ return tuple(string.split(self.absolute_url(1), '/')) def getReplies(self): """ Return a list of all objects that have their "in_reply_to" attribute set to my own URL """ result = [] my_url = self.absolute_url(1) talkback = self.aq_inner.aq_parent for item in talkback._container.values(): if item.in_reply_to == urllib.unquote(my_url): result.append(item.__of__(talkback)) return result def __call__(self, REQUEST, **kw): return apply(self.view, (self, REQUEST), kw) def edit(self, text_format, text, file='', REQUEST=None): """ Edit the discussion item. """ Document.edit(self, text_format, text, file) if REQUEST is not None: return self.editForm(self, REQUEST, portal_status_message= \ 'Discussion item changed.')
self.resp = resp def __del__(self): # Free the references. # # No errors of any sort may propagate, and we don't care *what* # they are, even to log them. try: del self.resp.unauthorized except: pass try: del self.resp._unauthorized except: pass try: del self.resp except: pass manage_addCCForm = HTMLFile('dtml/addCC', globals()) manage_addCCForm.__name__ = 'addCC' def _create_forms(ob): ''' Create default forms inside ob ''' import os from OFS.DTMLMethod import addDTMLMethod dtmldir = os.path.join(os.path.dirname(__file__), 'dtml') for fn in ('index_html', 'logged_in', 'logged_out', 'login_form', 'standard_login_footer', 'standard_login_header'): filename = os.path.join(dtmldir, fn + '.dtml') f = open(filename, 'rt') try: data = f.read() finally: f.close() addDTMLMethod(ob, fn, file=data)
__doc__ = """HTMLWidget Textarea module.""" __version__ = '2.1' import re import OFS.SimpleItem import Acquisition import AccessControl from Globals import HTMLFile, MessageDialog, Persistent, InitializeClass from DocumentTemplate.html_quote import html_quote from WidgetBase import WidgetBase, ValidationError, TALESMethod from IWidget import IWidget manage_addHTMLTextareaForm = HTMLFile('dtml/HTMLTextareaAdd', globals()) def manage_addHTMLTextarea(self, id, REQUEST=None): """Adds a new HTML Textarea Widget.""" self._setObject(id, HTMLTextarea(id, REQUEST)) if REQUEST is not None: REQUEST.RESPONSE.redirect(self.absolute_url() + "/manage_visualEdit") class HTMLTextarea(WidgetBase, OFS.SimpleItem.Item, Persistent, Acquisition.Implicit, AccessControl.Role.RoleManager): """HTMLWidget for Textareas""" __implements__ = IWidget
import pprint from Globals import HTMLFile from App.Management import Tabs from OFS.SimpleItem import Item from AccessControl import getSecurityManager, Unauthorized def filtered_manage_options(self, REQUEST=None): # Append an Introspection tab to an object's management tabs tabs = self._oldxxx_filtered_manage_options(REQUEST) secman = getSecurityManager() if len(tabs) \ and secman.checkPermission("Manage properties", self.this()): tabs.append({ 'label': 'Introspection', 'action': 'manage_introspection' }) return tabs Tabs._oldxxx_filtered_manage_options = Tabs.filtered_manage_options Tabs.filtered_manage_options = filtered_manage_options Item.manage_introspection = HTMLFile('zmi/manage_introspection', globals()) Item.introspection = introspection import logging logging.getLogger('ZMIntrospection').info("Applied patch.") except: import traceback traceback.print_exc()
class HTMLTextarea(WidgetBase, OFS.SimpleItem.Item, Persistent, Acquisition.Implicit, AccessControl.Role.RoleManager): """HTMLWidget for Textareas""" __implements__ = IWidget security = AccessControl.ClassSecurityInfo() security.declareProtected('View management screens', 'manage_properties') security = AccessControl.ClassSecurityInfo() meta_type = 'HTML Textarea' css_class = 'FormTextarea' user_css = '' aliases = [] colspan = 0 wrapping = 'virtual' manage_properties = HTMLFile('dtml/HTMLTextareaEdit', globals()) manage_options = ( { 'label': 'Properties', 'action': 'manage_properties' }, { 'label': 'Security', 'action': 'manage_access' }, ) ################## Some zopish management stuff def __init__(self, id, REQUEST=None): self.id = id self.__version__ = __version__ if REQUEST is not None: self.changeProperties(REQUEST) def __setstate__(self, state): HTMLTextarea.inheritedAttribute('__setstate__')(self, state) self._update_cache() security.declareProtected('Change Formulon instances', 'manage_edit') def manage_edit(self, REQUEST=None): """Sets the new properties.""" if REQUEST is not None: self.changeProperties(REQUEST) return MessageDialog(title='Edited', message="Properties for %s changed." % self.id, action='./manage_properties') security.declareProtected('Change Formulon instances', 'changeProperties') def changeProperties(self, REQUEST, encoding='iso-8859-1'): if REQUEST is None: return # Update the base properties self.changeBaseProperties(REQUEST, encoding) self.title = unicode(REQUEST.title, encoding) self.cols = REQUEST.cols self.rows = REQUEST.rows self.colspan = REQUEST.colspan self.aliases = REQUEST.aliases self.user_css = unicode(REQUEST.user_css, encoding) self.column = REQUEST.column if self.column < 1: self.column = 1 self.row = REQUEST.row if self.row < 1: self.row = 1 if REQUEST.has_key("wrapping"): self.wrapping = REQUEST["wrapping"] # Update TALES Methods tales = ['default', 'regexp', 'hint'] for x in tales: expression = REQUEST.get(x) if expression is None: continue setattr(self, x, TALESMethod(unicode(expression, encoding))) # cache the compiled regular expression: self._update_cache() def _update_cache(self): """Compiles a volatile attribute for caching the regex.""" self._v_regex = self._compile_regex() def _compile_regex(self, force=False): """Compiles the regex attribute. If force is False regex is only compiled if it starts with 'string:'. (This is for the cache.) """ if force or self.regexp.getExpression().startswith('string:'): try: return re.compile(self.callMethod(self.regexp), re.DOTALL) except AttributeError: # happens creating new widget because callMethod needs aq_parent return None #################### The widget specific code security.declareProtected('View', 'render') def render(self, parent, tabindex=None): doc = parent.ownerDocument node = parent.appendChild(doc.createElement("textarea")) if tabindex is not None: node.setAttribute("tabindex", str(tabindex)) if self.user_css: node.setAttribute("class", self.user_css) else: node.setAttribute("class", self.css_class) node.setAttribute("name", self.id + "_value") node.setAttribute("cols", str(self.cols)) node.setAttribute("rows", str(self.rows)) node.setAttribute("wrapping", self.wrapping) node.setAttribute("onChange", "reportChange(this)") node.appendChild(doc.createTextNode(self.value())) return node security.declareProtected('View', 'validate') def validate(self, against=None): __traceback_info__ = self.getId(), against against = against["value"] if isinstance(against, str): against = unicode(against, self.site_encoding) regex = getattr(self, '_v_regex', None) if regex is None: regex = self._compile_regex() if regex is not None: # starts with 'string:' so save it self._v_regex = regex else: regex = self._compile_regex(force=True) if not len(regex.findall(against)): raise ValidationError(self.callMethod(self.hint)) return against security.declareProtected('View', 'height') def height(self): height = self.rows - 2 if height < 1: height = 1 return height security.declareProtected('View', 'value') def value(self): try: a = self.REQUEST['__source_data__'][self.id] if a is None: a = '' return a except KeyError: pass try: return self.REQUEST[self.id] except KeyError: pass return self.callMethod(self.default) security.declareProtected('View', 'getValue') getValue = value
return rval security.declareProtected(AccessContentsInformation, 'getDirPath') def getDirPath(self): return self.__dict__['_real']._dirpath security.declarePublic('getId') def getId(self): return self.id InitializeClass(DirectoryViewSurrogate) manage_addDirectoryViewForm = HTMLFile('dtml/addFSDirView', globals()) def createDirectoryView(parent, minimal_fp, id=None): """ Add either a DirectoryView or a derivative object. """ info = _dirreg.getDirectoryInfo(minimal_fp) if info is None: raise ValueError('Not a registered directory: %s' % minimal_fp) if not id: id = minimal_fp.split('/')[-1] else: id = str(id) ob = DirectoryView(id, minimal_fp) parent._setObject(id, ob)
try: from Products.GenericSetup.interfaces import IDAVAware except ImportError: IDAVAware = None here = package_home(globals()) ViewPermission = Permissions.view AccessPermission = Permissions.view_management_screens ChangePermission = 'Change ExtFile/ExtImage' DownloadPermission = 'Download ExtFile/ExtImage' from configuration import * manage_addExtFileForm = HTMLFile('www/extFileAdd', globals()) def manage_addExtFile(self, id='', title='', descr='', file='', content_type='', permission_check=0, redirect_default_view=0, REQUEST=None): """ Add an ExtFile to a folder. """ if not id and getattr(file, 'filename', None) is not None: # generate id from filename and make sure, it has no 'bad' chars id = file.filename
class HTMLFileupload(WidgetBase, OFS.SimpleItem.Item, Persistent, Acquisition.Implicit, AccessControl.Role.RoleManager): """HTMLWidget for Fileuploads""" __implements__ = IWidget security = AccessControl.ClassSecurityInfo() meta_type = 'HTML Fileupload' css_class = 'FormFileupload' colspan = 1 required = 0 aliases = [] security.declareProtected('View management screens', 'manage_properties') manage_properties = HTMLFile('dtml/HTMLFileuploadEdit', globals()) manage_options = ( { 'label': 'Properties', 'action': 'manage_properties' }, { 'label': 'Security', 'action': 'manage_access' }, ) ################ Here comes Zope specific code def __init__(self, id, REQUEST): self.id = id self.__version__ = __version__ if REQUEST is not None: self.changeProperties(REQUEST) security.declareProtected('Change Formulon instances', 'manage_edit') def manage_edit(self, REQUEST=None): """ set the new properties """ if REQUEST is not None: self.changeProperties(REQUEST) return MessageDialog(title='Edited', message="Properties for %s changed." % self.id, action='./manage_properties') security.declareProtected('Change Formulon instances', 'changeProperties') def changeProperties(self, REQUEST=None, encoding='iso-8859-1'): if REQUEST is None: return # Update the base properties self.changeBaseProperties(REQUEST, encoding) self.title = unicode(REQUEST.title, encoding) self.column = REQUEST.column if self.column < 1: self.column = 1 self.row = REQUEST.row if self.row < 1: self.row = 1 self.colspan = REQUEST.colspan self.required = 0 if REQUEST.has_key('required'): self.required = 1 self.aliases = REQUEST.aliases # Update TALES Methods for x in ['hint']: expression = REQUEST.get(x) if expression is None: continue setattr(self, x, TALESMethod(unicode(expression, encoding))) ################# Here comes the widget specific code security.declareProtected('View', 'render') def render(self, parent, tabindex=None): doc = parent.ownerDocument widget = parent.appendChild(doc.createElement('input')) set = widget.setAttribute if tabindex is not None: set('tabindex', str(tabindex)) set('name', self.id + "_value") set('type', 'file') set('class', self.css_class) set("onChange", "reportChange(this)") return widget security.declareProtected('View', 'validate') def validate(self, against): filename = '' against = against.get('value') if isinstance(against, ZPublisher.HTTPRequest.FileUpload): filename = against.filename if self.required and not filename: raise ValidationError(self.callMethod(self.hint)) return against security.declareProtected('View', 'height') def height(self): return 1 security.declareProtected('View', 'getValue') def getValue(self): if self.REQUEST.has_key(self.id): return self.REQUEST[self.id] else: return None
class ExtFile(CatalogAware, SimpleItem, PropertyManager, Cacheable): """ The ExtFile-Product works like the Zope File-product, but stores the uploaded file externally in a repository-directory. """ if IDAVAware is not None: interface.implements(IExtFile, IDAVAware) else: interface.implements(IExtFile) # BBB __implements__ = (WriteLockInterface, ) # what properties have we? _properties = ( { 'id': 'title', 'type': 'string', 'mode': 'w' }, { 'id': 'descr', 'type': 'text', 'mode': 'w' }, { 'id': 'content_type', 'type': 'string', 'mode': 'w' }, { 'id': 'use_download_permission_check', 'type': 'boolean', 'mode': 'w' }, { 'id': 'redirect_default_view', 'type': 'boolean', 'mode': 'w' }, ) use_download_permission_check = 0 redirect_default_view = 0 # what management options are there? manage_options = (( { 'label': 'Edit', 'action': 'manage_main' }, { 'label': 'View', 'action': '' }, { 'label': 'Upload', 'action': 'manage_uploadForm' }, ) + PropertyManager.manage_options + SimpleItem.manage_options[1:] + Cacheable.manage_options) security = ClassSecurityInfo() # what do people think they're adding? meta_type = 'ExtFile' # make sure the download permission is available security.setPermissionDefault(DownloadPermission, ('Manager', )) # MIME-Type Dictionary. To add a MIME-Type, add a file in the directory # icons/_category_/_subcategory-icon-file_ # example: Icon tifficon.gif for the MIME-Type image/tiff goes to # icons/image/tifficon.gif and the dictionary must be updated like this: # 'image':{'tiff':'tifficon.gif','default':'default.gif'}, ... _types = { 'image': { 'default': 'default.gif' }, 'text': { 'html': 'html.gif', 'xml': 'xml.gif', 'default': 'default.gif', 'python': 'py.gif' }, 'application': { 'pdf': 'pdf.gif', 'zip': 'zip.gif', 'tar': 'zip.gif', 'msword': 'doc.gif', 'excel': 'xls.gif', 'powerpoint': 'ppt.gif', 'default': 'default.gif' }, 'video': { 'default': 'default.gif' }, 'audio': { 'default': 'default.gif' }, 'default': 'default.gif' } ################################ # Init method # ################################ def __init__(self, id, title='', descr='', permission_check=0, redirect_default_view=0): """ Initialize a new instance of ExtFile """ self.id = id self.title = title self.descr = descr self.use_download_permission_check = permission_check self.redirect_default_view = redirect_default_view self.__version__ = __version__ self.filename = [] self.content_type = '' ################################ # Public methods # ################################ def __str__(self): return self.index_html() def __len__(self): return 1 def _if_modified_since_request_handler(self, REQUEST): """ HTTP If-Modified-Since header handling: return True if we can handle this request by returning a 304 response. """ header = REQUEST.get_header('If-Modified-Since', None) if header is not None: header = string.split(header, ';')[0] try: mod_since = long(DateTime(header).timeTime()) except: mod_since = None if mod_since is not None: if self._p_mtime: last_mod = long(self._p_mtime) else: last_mod = long(0) if last_mod > 0 and last_mod <= mod_since: # Set headers for Apache caching last_mod = rfc1123_date(self._p_mtime) REQUEST.RESPONSE.setHeader('Last-Modified', last_mod) REQUEST.RESPONSE.setHeader('Content-Type', self.content_type) # RFC violation. See http://www.zope.org/Collectors/Zope/544 #REQUEST.RESPONSE.setHeader('Content-Length', self.get_size()) REQUEST.RESPONSE.setStatus(304) return 1 def _redirect_default_view_request_handler(self, icon, preview, REQUEST): """ redirect_default_view property handling: return True if we can handle this request by returning a 302 response. Patch provided by Oliver Bleutgen. """ if self.redirect_default_view: if self.static_mode() and not icon: static_url = self._static_url(preview=preview) if static_url != self.absolute_url(): REQUEST.RESPONSE.redirect(static_url) return 1 security.declareProtected(ViewPermission, 'index_html') def index_html(self, icon=0, preview=0, width=None, height=None, REQUEST=None): """ Return the file with it's corresponding MIME-type """ if REQUEST is not None: if self._if_modified_since_request_handler(REQUEST): self.ZCacheable_set(None) return '' if self._redirect_default_view_request_handler( icon, preview, REQUEST): return '' filename, content_type, icon, preview = self._get_file_to_serve( icon, preview) filename = self._get_fsname(filename) if _debug > 1: logger.info('serving %s, %s, %s, %s' % (filename, content_type, icon, preview)) if filename: size = os.stat(filename)[6] else: filename = self._get_icon_file(broken=True) size = os.stat(filename)[6] content_type = 'image/gif' icon = 1 if icon == 0 and width is not None and height is not None: data = TemporaryFile() # hold resized image try: from PIL import Image im = Image.open(filename) if im.mode != 'RGB': im = im.convert('RGB') filter = Image.BICUBIC if hasattr(Image, 'ANTIALIAS'): # PIL 1.1.3 filter = Image.ANTIALIAS im = im.resize((int(width), int(height)), filter) im.save(data, 'JPEG', quality=85) except: data = open(filename, 'rb') else: data.seek(0, 2) size = data.tell() data.seek(0) content_type = 'image/jpeg' else: data = open(filename, 'rb') if REQUEST is not None: last_mod = rfc1123_date(self._p_mtime) REQUEST.RESPONSE.setHeader('Last-Modified', last_mod) REQUEST.RESPONSE.setHeader('Content-Type', content_type) REQUEST.RESPONSE.setHeader('Content-Length', size) self.ZCacheable_set(None) return stream_iterator(data) try: return data.read() finally: data.close() security.declareProtected(ViewPermission, 'view_image_or_file') def view_image_or_file(self): """ The default view of the contents of the File or Image. """ raise Redirect(self.absolute_url()) security.declareProtected(ViewPermission, 'link') def link(self, text='', **args): """ Return an HTML link tag to the file or image. Assumes all arguments are properly quoted. """ if not text: text = html_quote(self.title_or_id()) return self._link(self._static_url(), text, **args) security.declareProtected(ViewPermission, 'icon_gif') def icon_gif(self): """ Return an icon for the file's MIME-Type """ raise Redirect(self._static_url(icon=1)) security.declareProtected(ViewPermission, 'icon_tag') def icon_tag(self): """ Generate the HTML IMG tag for the icon """ return '<img src="%s" border="0" />' % self._static_url(icon=1) security.declareProtected(ViewPermission, 'icon_html') def icon_html(self): """ Same as icon_tag """ return self.icon_tag() security.declareProtected(ViewPermission, 'is_broken') def is_broken(self): """ Check if external file exists and return true (1) or false (0) """ return not self._get_fsname(self.filename) security.declareProtected(ViewPermission, 'get_size') def get_size(self): """ Returns the size of the file or image """ fn = self._get_fsname(self.filename) if fn: return os.stat(fn)[6] return 0 security.declareProtected(ViewPermission, 'rawsize') def rawsize(self): """ Same as get_size """ return self.get_size() security.declareProtected(ViewPermission, 'getSize') def getSize(self): """ Same as get_size """ return self.get_size() security.declareProtected(ViewPermission, 'size') def size(self): """ Returns a formatted stringified version of the file size """ return self._bytetostring(self.get_size()) security.declareProtected(ViewPermission, 'getContentType') def getContentType(self): """ Returns the content type (MIME type) of a file or image. """ return self.content_type security.declareProtected(ViewPermission, 'getIconPath') def getIconPath(self, broken=False): """ Depending on the MIME Type of the file/image an icon can be displayed. This function determines which image in the Products/ExtFile/www/icons/... directory should be used as icon for this file/image. """ if broken: return join('www', 'icons', 'broken.gif') try: cat, sub = string.split(self.content_type, '/') except ValueError: if getattr(self, 'has_preview', None) is not None: cat, sub = 'image', '' else: cat, sub = '', '' if self._types.has_key(cat): file = self._types[cat]['default'] for item in self._types[cat].keys(): if string.find(sub, item) >= 0: file = self._types[cat][item] break return join('www', 'icons', cat, file) return join('www', 'icons', self._types['default']) security.declareProtected(ViewPermission, 'static_url') def static_url(self, icon=0, preview=0): """ Returns the static url of the file """ return self._static_url(icon, preview) security.declareProtected(ViewPermission, 'static_mode') def static_mode(self): """ Returns true if serving static urls """ return os.environ.get('EXTFILE_STATIC_PATH') is not None security.declareProtected(AccessPermission, 'get_filename') def get_filename(self): """ Returns the filename as file system path. Used by the ZMI to display the filename. """ return self._fsname(self.filename) security.declareProtected(ViewPermission, 'PrincipiaSearchSource') def PrincipiaSearchSource(self): """ Allow file objects to be searched. """ if self.content_type.startswith('text/'): return str(self) return '' ################################ # Protected management methods # ################################ # Management Interface security.declareProtected(AccessPermission, 'manage_main') manage_main = HTMLFile('www/extFileEdit', globals()) security.declareProtected(ChangePermission, 'manage_editExtFile') def manage_editExtFile(self, title='', descr='', REQUEST=None): """ Manage the edited values """ if self.title != title: self.title = title if self.descr != descr: self.descr = descr # update ZCatalog self.reindex_object() self.ZCacheable_invalidate() if REQUEST is not None: return self.manage_main(self, REQUEST, manage_tabs_message='Saved changes.') # File upload Interface security.declareProtected(AccessPermission, 'manage_uploadForm') manage_uploadForm = HTMLFile('www/extFileUpload', globals()) security.declareProtected(ChangePermission, 'manage_upload') def manage_upload(self, file='', content_type='', REQUEST=None): """ Upload file from file handle or string buffer """ if self.wl_isLocked(): raise ResourceLockedError("File is locked via WebDAV") if isinstance(file, str): temp_file = TemporaryFile() temp_file.write(file) temp_file.seek(0) else: temp_file = file return self.manage_file_upload(temp_file, content_type, REQUEST) security.declareProtected(ChangePermission, 'manage_file_upload') def manage_file_upload(self, file='', content_type='', REQUEST=None): """ Upload file from file handle or local directory """ if self.wl_isLocked(): raise ResourceLockedError("File is locked via WebDAV") if isinstance(file, str): file = open(file, 'rb') if content_type: file = HTTPUpload(file, content_type) content_type = self._get_content_type(file, file.read(100), self.id, self.content_type) file.seek(0) self._register() # Register with TM try: backup = REPOSITORY_EXTENSIONS in (MIMETYPE_APPEND, MIMETYPE_REPLACE) and \ self.filename and self.content_type != content_type new_fn = self._get_ufn(self.filename, content_type=content_type, backup=backup) self._update_data(file, self._temp_fsname(new_fn)) finally: self._dir__unlock() self.filename = new_fn self.content_type = content_type self._afterUpdate() if REQUEST is not None: return self.manage_main(self, REQUEST, manage_tabs_message='Upload complete.') security.declareProtected(ChangePermission, 'manage_http_upload') def manage_http_upload(self, url, REQUEST=None): """ Upload file from http-server """ if self.wl_isLocked(): raise ResourceLockedError("File is locked via WebDAV") url = urllib.quote(url, '/:') file = urllib.urlopen(url) file = HTTPUpload(file) content_type = self._get_content_type(file, file.read(100), self.id, self.content_type) file.seek(0) self._register() # Register with TM try: backup = REPOSITORY_EXTENSIONS in (MIMETYPE_APPEND, MIMETYPE_REPLACE) and \ self.filename and self.content_type != content_type new_fn = self._get_ufn(self.filename, content_type=content_type, backup=backup) self._update_data(file, self._temp_fsname(new_fn)) finally: self._dir__unlock() self.filename = new_fn self.content_type = content_type self._afterUpdate() if REQUEST is not None: return self.manage_main(self, REQUEST, manage_tabs_message='Upload complete.') security.declareProtected(ChangePermission, 'PUT') def PUT(self, REQUEST, RESPONSE): """ Handle HTTP PUT requests """ self.dav__init(REQUEST, RESPONSE) self.dav__simpleifhandler(REQUEST, RESPONSE, refresh=1) file = REQUEST['BODYFILE'] content_type = REQUEST.get_header('content-type', None) if content_type: file = HTTPUpload(file, content_type) content_type = self._get_content_type(file, file.read(100), self.id, self.content_type) file.seek(0) self._register() # Register with TM try: backup = REPOSITORY_EXTENSIONS in (MIMETYPE_APPEND, MIMETYPE_REPLACE) and \ self.filename and self.content_type != content_type new_fn = self._get_ufn(self.filename, content_type=content_type, backup=backup) self._update_data(file, self._temp_fsname(new_fn)) finally: self._dir__unlock() self.filename = new_fn self.content_type = content_type self._afterUpdate() RESPONSE.setStatus(204) return RESPONSE security.declareProtected('FTP access', 'manage_FTPstat') security.declareProtected('FTP access', 'manage_FTPlist') security.declareProtected('FTP access', 'manage_FTPget') def manage_FTPget(self): """ Return body for FTP """ return self.index_html(REQUEST=self.REQUEST) ################################ # Private methods # ################################ def _access_permitted(self, REQUEST=None): """ Check if the user is allowed to download the file """ if REQUEST is None and getattr(self, 'REQUEST', None) is not None: REQUEST = self.REQUEST if getattr(self, 'use_download_permission_check', 0) and \ (REQUEST is None or not getSecurityManager().getUser().has_permission( DownloadPermission, self) ): return 0 else: return 1 def _get_content_type(self, file, body, id, content_type=None): """ Determine the mime-type """ headers = getattr(file, 'headers', None) if headers and headers.has_key('content-type'): content_type = headers['content-type'] else: filename = getattr(file, 'filename', None) or id content_type, enc = guess_content_type(filename, body, content_type) cutoff = content_type.find(';') if cutoff >= 0: return content_type[:cutoff] return content_type def _update_data(self, infile, outfile): """ Store infile to outfile """ if isinstance(infile, list): infile = self._fsname(infile) if isinstance(outfile, list): outfile = self._fsname(outfile) try: self._copy(infile, outfile) except: if isfile(outfile): # This is always a .tmp file try: os.remove(outfile) except OSError: logger.error('_update_data', exc_info=True) raise else: self.http__refreshEtag() def _copy(self, infile, outfile): """ Read binary data from infile and write it to outfile infile and outfile may be strings, in which case a file with that name is opened, or filehandles, in which case they are accessed directly. """ if isinstance(infile, str): instream = open(infile, 'rb') close_in = 1 else: instream = infile close_in = 0 if isinstance(outfile, str): umask = os.umask(REPOSITORY_UMASK) try: outstream = open(outfile, 'wb') self._dir__unlock() # unlock early finally: os.umask(umask) close_out = 1 else: outstream = outfile close_out = 0 blocksize = 2 << 16 block = instream.read(blocksize) outstream.write(block) while len(block) == blocksize: block = instream.read(blocksize) outstream.write(block) try: instream.seek(0) except: pass if close_in: instream.close() if close_out: outstream.close() def _delete(self, filename): """ Rename the file to .undo """ tmp_fn = self._temp_fsname(filename) old_fn = self._fsname(filename) if isfile(tmp_fn): try: os.rename(tmp_fn, old_fn + '.undo') except OSError: logger.error('_delete', exc_info=True) else: if isfile(old_fn): try: os.remove(old_fn) except OSError: logger.error('_delete', exc_info=True) elif isfile(old_fn): try: os.rename(old_fn, old_fn + '.undo') except OSError: logger.error('_delete', exc_info=True) def _undo(self, filename): """ Restore filename after delete or copy-paste """ fn = self._fsname(filename) if not isfile(fn) and isfile(fn + '.undo'): self._register() # Register with TM os.rename(fn + '.undo', self._temp_fsname(filename)) def _fsname(self, filename): """ Generates the full filesystem name, incuding directories from REPOSITORY_PATH and filename """ path = [INSTANCE_HOME] path.extend(REPOSITORY_PATH) if isinstance(filename, list): path.extend(filename) elif filename != '': path.append(filename) return join(*path) def _temp_fsname(self, filename): """ Generates the full filesystem name of the temporary file """ return '%s.tmp' % self._fsname(filename) def _get_fsname(self, filename): """ Returns the full filesystem name, preferring tmp over main. Also attempts to undo. Returns None if the file is broken. """ tmp_fn = self._temp_fsname(filename) if isfile(tmp_fn): return tmp_fn fn = self._fsname(filename) if isfile(fn): return fn self._undo(filename) if isfile(tmp_fn): return tmp_fn def _get_ufn(self, filename, path=None, content_type=None, lock=1, backup=0): """ If no unique filename has been generated, generate one. Otherwise, return the existing one. """ if UNDO_POLICY == ALWAYS_BACKUP or backup or filename == []: new_fn = self._get_new_ufn(path=path, content_type=content_type, lock=lock) else: new_fn = filename[:] if filename: if UNDO_POLICY == ALWAYS_BACKUP or backup: self._delete(filename) else: self._undo(filename) return new_fn def _get_new_ufn(self, path=None, content_type=None, lock=1): """ Create a new unique filename """ id = self.id # hack so the files are not named copy_of_foo if COPY_OF_PROTECTION: id = copy_of_protect(id) # get name and extension components from id pos = string.rfind(id, '.') if (pos + 1): id_name = id[:pos] id_ext = id[pos:] else: id_name = id id_ext = '' if not content_type: content_type = self.content_type if REPOSITORY_EXTENSIONS in (MIMETYPE_APPEND, MIMETYPE_REPLACE): mime_ext = guess_extension(content_type) if mime_ext is not None: # don't change extensions of unknown binaries and text files if not (content_type in config.unknown_types and id_ext): if REPOSITORY_EXTENSIONS == MIMETYPE_APPEND: # don't append the same extension twice if id_ext != mime_ext: id_name = id_name + id_ext id_ext = mime_ext # generate directory structure if path is not None: rel_url_list = path else: rel_url_list = self._get_zodb_path() dirs = [] if REPOSITORY == SYNC_ZODB: dirs = rel_url_list elif REPOSITORY in (SLICED, SLICED_REVERSE, SLICED_HASH): if REPOSITORY == SLICED_HASH: # increase distribution by including the path in the hash hashed = ''.join(list(rel_url_list) + [id_name]) temp = base64.encodestring(sha.new(hashed).digest())[:-1] temp = temp.replace('/', '_') temp = temp.replace('+', '_') elif REPOSITORY == SLICED_REVERSE: temp = list(id_name) temp.reverse() temp = ''.join(temp) else: temp = id_name for i in range(SLICE_DEPTH): if len(temp) < SLICE_WIDTH * (SLICE_DEPTH - i): dirs.append(SLICE_WIDTH * '_') else: dirs.append(temp[:SLICE_WIDTH]) temp = temp[SLICE_WIDTH:] elif REPOSITORY == CUSTOM: method = aq_acquire(self, CUSTOM_METHOD) dirs = method(rel_url_list, id) if NORMALIZE_CASE == NORMALIZE: dirs = [d.lower() for d in dirs] # make directories dirpath = self._fsname(dirs) if not os.path.isdir(dirpath): umask = os.umask(REPOSITORY_UMASK) try: os.makedirs(dirpath) finally: os.umask(umask) # generate file name fileformat = FILE_FORMAT # time/counter (%t) if string.find(fileformat, "%t") >= 0: fileformat = string.replace(fileformat, "%t", "%c") counter = int(DateTime().strftime('%m%d%H%M%S')) else: counter = 0 if string.find(fileformat, "%c") == -1: raise ValueError("Invalid file format '%s'" % FILE_FORMAT) # user (%u) if string.find(fileformat, "%u") >= 0: if (getattr(self, 'REQUEST', None) is not None and self.REQUEST.has_key('AUTHENTICATED_USER')): user = getSecurityManager().getUser().getUserName() fileformat = string.replace(fileformat, "%u", user) else: fileformat = string.replace(fileformat, "%u", "") # path (%p) if string.find(fileformat, "%p") >= 0: temp = string.joinfields(rel_url_list, "_") fileformat = string.replace(fileformat, "%p", temp) # file and extension (%n and %e) if string.find(fileformat, "%n") >= 0 or string.find(fileformat, "%e") >= 0: fileformat = string.replace(fileformat, "%n", id_name) fileformat = string.replace(fileformat, "%e", id_ext) # lock the directory if lock: self._dir__lock(dirpath) # search for unique filename if counter: fn = join(dirpath, string.replace(fileformat, "%c", ".%s" % counter)) else: fn = join(dirpath, string.replace(fileformat, "%c", '')) while isfile(fn) or isfile(fn + '.undo') or isfile(fn + '.tmp'): counter = counter + 1 fn = join(dirpath, string.replace(fileformat, "%c", ".%s" % counter)) if counter: fileformat = string.replace(fileformat, "%c", ".%s" % counter) else: fileformat = string.replace(fileformat, "%c", '') dirs.append(fileformat) return dirs def _static_url(self, icon=0, preview=0): """ Return the static url of the file """ static_path = os.environ.get('EXTFILE_STATIC_PATH') if static_path is not None: filename, content_type, icon, preview = \ self._get_file_to_serve(icon, preview) if icon: # cannot serve statically return '%s?icon=1' % self.absolute_url() else: # rewrite to static url static_host = os.environ.get('EXTFILE_STATIC_HOST') host = self.REQUEST.SERVER_URL if static_host is not None: if host[:8] == 'https://': host = 'https://' + static_host else: host = 'http://' + static_host host = host + urllib.quote(static_path) + '/' return host + urllib.quote('/'.join(filename)) else: if icon: return '%s?icon=1' % self.absolute_url() elif preview: return '%s?preview=1' % self.absolute_url() else: return self.absolute_url() def _get_file_to_serve(self, icon=0, preview=0): """ Find out about the file we are going to serve """ if not self._access_permitted(): preview = 1 if preview and not getattr(self, 'has_preview', 0): icon = 1 if icon: filename = self._get_icon_file() content_type = 'image/gif' elif preview: filename = self.prev_filename content_type = self.prev_content_type else: filename = self.filename content_type = self.content_type return filename, content_type, icon, preview def _get_icon_file(self, broken=False): """ Returns the filesystem path of the icon corresponding to self.content_type. If broken is True, returns the filesystem path of the "broken" icon. """ return join(here, self.getIconPath(broken)) def _get_zodb_path(self, parent=None): """ Returns the ZODB path of the parent object """ if parent is None: parent = self.aq_parent if ZODB_PATH == VIRTUAL: path = parent.absolute_url(1).split('/') else: path = list(parent.getPhysicalPath()) return filter(None, path) def _link(self, href, text, **args): """ Returns an HTML link tag. Assumes all arguments are properly quoted. """ strg = '<a href="%s"' % (href, ) for key in args.keys(): value = args.get(key) strg = '%s %s="%s"' % (strg, key, value) strg = '%s>%s</a>' % (strg, text) return strg def _bytetostring(self, value): """ Convert an int-value (file-size in bytes) to an String with the file-size in Byte, KB or MB """ bytes = float(value) if bytes >= 1000: bytes = bytes / 1024 if bytes >= 1000: bytes = bytes / 1024 typ = ' MB' else: typ = ' KB' else: typ = ' Bytes' strg = '%4.2f' % bytes strg = strg[:4] if strg[3] == '.': strg = strg[:3] strg = strg + typ return strg def _afterUpdate(self): """ Called whenever the file data has been updated. Fires an ExtFileUpdatedEvent. """ self.ZCacheable_invalidate() event.notify(ExtFileUpdatedEvent(self)) ################################ # Special management methods # ################################ security.declarePrivate('get_fsname') def get_fsname(self): """ Returns the current file system path of the file or image. This path can be used to access the file even while a transaction is in progress (aka Zagy's revenge :-). Returns None if the file does not exist in the repository. """ return self._get_fsname(self.filename) ################################ # Repository locking methods # ################################ def _dir__lock(self, dir): """ Lock a directory """ if hasattr(self, '_v_dir__lock'): raise DirLockError('Double lock in thread') self._v_dir__lock = DirLock(dir) def _dir__unlock(self): """ Unlock a previously locked directory """ if hasattr(self, '_v_dir__lock'): self._v_dir__lock.release() delattr(self, '_v_dir__lock') ################################ # Transaction manager methods # ################################ def _register(self): if _debug: logger.info('registering %s' % TM.contains(self)) TM.register(self) if _debug: logger.info('registered %s' % TM.contains(self)) def _begin(self): self._v_begin_called = 1 # for tests if _debug: logger.info('beginning %s' % self.id) def _finish(self): """ Commits the temporary file """ self._v_finish_called = 1 # for tests TM.remove(self) # for tests if self.filename: tmp_fn = self._temp_fsname(self.filename) if _debug: logger.info('finishing %s' % tmp_fn) if isfile(tmp_fn): if _debug: logger.info('isfile %s' % tmp_fn) fn = self._fsname(self.filename) if isfile(fn): try: os.remove(fn) except OSError: logger.error('_finish', exc_info=True) try: os.rename(tmp_fn, fn) except OSError: logger.error('_finish', exc_info=True) def _abort(self): """ Deletes the temporary file """ self._v_abort_called = 1 # for tests TM.remove(self) # for tests if self.filename: tmp_fn = self._temp_fsname(self.filename) if _debug: logger.info('aborting %s' % tmp_fn) if isfile(tmp_fn): if _debug: logger.info('isfile %s' % tmp_fn) try: os.remove(tmp_fn) except OSError: logger.error('_abort', exc_info=True)