Ejemplo n.º 1
0
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',
            )
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
#
# $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
Ejemplo n.º 7
0
        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.
    '''
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
        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.
Ejemplo n.º 12
0
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)
Ejemplo n.º 13
0
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',
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
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
Ejemplo n.º 16
0
                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)
Ejemplo n.º 17
0
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()
Ejemplo n.º 18
0
        """
        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)
Ejemplo n.º 19
0
        # 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:
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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,
Ejemplo n.º 22
0
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
    '''
Ejemplo n.º 23
0
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'
Ejemplo n.º 24
0
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.')
Ejemplo n.º 25
0
        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)
Ejemplo n.º 26
0
__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
Ejemplo n.º 27
0
    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()
Ejemplo n.º 28
0
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
Ejemplo n.º 29
0
        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)
Ejemplo n.º 30
0
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
Ejemplo n.º 31
0
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
Ejemplo n.º 32
0
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)