Esempio n. 1
0
def getToolByName(obj, name, default=_marker):

    """ Get the tool, 'toolname', by acquiring it.

    o Application code should use this method, rather than simply
      acquiring the tool by name, to ease forward migration (e.g.,
      to Zope3).
    """
    tool_interface = _tool_interface_registry.get(name)

    if tool_interface is not None:
        warn('getToolByName is deprecated and will be removed in '
             'CMF 2.3, please use "getUtility(%s)"' % (
               tool_interface.__name__), DeprecationWarning, stacklevel=2) 

        try:
            return getUtility(tool_interface)
        except ComponentLookupError:
            # behave in backwards-compatible way
            # fall through to old implementation
            pass
    
    try:
        tool = aq_get(obj, name, default, 1)
    except AttributeError:
        if default is _marker:
            raise
        return default
    else:
        if tool is _marker:
            raise AttributeError, name
        return tool
Esempio n. 2
0
def ignore_link_integrity_exceptions(site):
    error_log = aq_get(site, 'error_log')
    props = error_log.getProperties()
    exceptions = props['ignored_exceptions']
    exceptions = exceptions + ('LinkIntegrityNotificationException', )
    error_log.setProperties(props['keep_entries'],
        ignored_exceptions=tuple(sorted(set(exceptions))))
Esempio n. 3
0
    def getOwner(self, info=0,
                 aq_get=aq_get,
                 UnownableOwner=UnownableOwner,
                 getSecurityManager=getSecurityManager,
                 ):
        """Get the owner

        If a true argument is provided, then only the owner path and id are
        returned. Otherwise, the owner object is returned.
        """
        if info:
            import warnings
            warnings.warn('Owned.getOwner(1) is deprecated; '
                          'please use getOwnerTuple() instead.',
                          DeprecationWarning, stacklevel=2)


        owner=aq_get(self, '_owner', None, 1)
        if info or (owner is None): return owner

        if owner is UnownableOwner: return None

        udb, oid = owner

        root=self.getPhysicalRoot()
        udb=root.unrestrictedTraverse(udb, None)
        if udb is None:
            user = SpecialUsers.nobody
        else:
            user = udb.getUserById(oid, None)
            if user is None: user = SpecialUsers.nobody
        return user
Esempio n. 4
0
    def __call__(self, id, instance, *args, **kwargs):
        try:
            # try to use the check_id script of CMFPlone
            check_id = aq_get(instance, 'check_id', None, 1)
            if check_id is None:
                raise AttributeError('check_id script not found')
            return check_id(id, required=kwargs.get('required', 0)) or 1
        except AttributeError:
            # space test
            if ' ' in id:
                msg =  _(u'Spaces are not allowed in ids')
                return recursiveTranslate(msg, **kwargs)

            # in parent test
            parent = aq_parent(aq_inner(instance))
            # If the id is given to a different object already
            if id in parent.objectIds() and getattr(aq_base(parent), id) is not aq_base(instance):
                msg = _(u'Id $id is already in use',
                        mapping = {'id': safe_unicode(id)})
                return recursiveTranslate(msg, **kwargs)

            # objet manager test
            # XXX: This is f***ed
            try:
                ObjectManager.checkValidId(self, id, allow_dup=1)
            except BadRequest, m:
                return str(m)
            return 1
Esempio n. 5
0
    def __call__(self, context):
        site = getSite()
        wtool = getToolByName(site, "portal_workflow", None)
        if wtool is None:
            return SimpleVocabulary([])

        transitions = {}
        for wf in wtool.values():
            transition_folder = getattr(wf, "transitions", None)
            wf_name = wf.title or wf.id
            if transition_folder is not None:

                for transition in transition_folder.values():

                    # zope.i18nmessageid will choke
                    # if undecoded UTF-8 bytestrings slip through
                    # which we may encounter on international sites
                    # where transition names are in local language.
                    # This may break overlying functionality even
                    # if the terms themselves are never used
                    name = safe_unicode(transition.actbox_name)

                    transition_title = translate(_(name), context=aq_get(wtool, "REQUEST", None))
                    transitions.setdefault(transition.id, []).append(dict(title=transition_title, wf_name=wf_name))
        items = []
        transition_items = transitions.items()
        transition_items.sort(key=lambda transition: transition[0])
        for transition_id, info in transition_items:
            titles = set([i["title"] for i in info])
            item_title = " // ".join(sorted(titles))
            item_title = "%s [%s]" % (item_title, transition_id)
            items.append(SimpleTerm(transition_id, transition_id, item_title))

        return SimpleVocabulary(items)
Esempio n. 6
0
    def __call__(self, context):
        site = getSite()
        wtool = getToolByName(site, 'portal_workflow', None)
        if wtool is None:
            return SimpleVocabulary([])

        # XXX This is evil. A vocabulary shouldn't be request specific.
        # The sorting should go into a separate widget.

        # we get REQUEST from wtool because context may be an adapter
        request = aq_get(wtool, 'REQUEST', None)

        items = wtool.listWFStatesByTitle(filter_similar=True)
        items = [(safe_unicode(i[0]), i[1]) for i in items]
        items_dict = dict(  # no dict comprehension in py 2.6
            [
                (i[1], translate(_(i[0]), context=request))
                for i in items
            ]
        )
        items_list = [(k, v) for k, v in items_dict.items()]
        items_list.sort(lambda x, y: cmp(x[1], y[1]))
        terms = [
            SimpleTerm(k, title=u'%s [%s]' % (v, k))
            for k, v in items_list
        ]
        return SimpleVocabulary(terms)
Esempio n. 7
0
 def assignTitles(self, portal, out):
     titles={'portal_actions':'Contains custom tabs and buttons',
      'portal_membership':'Handles membership policies',
      'portal_memberdata':'Handles the available properties on members',
      'portal_undo':'Defines actions and functionality related to undo',
      'portal_types':'Controls the available content types in your portal',
      'plone_utils':'Various utility methods',
      'portal_metadata':'Controls metadata like keywords, copyrights, etc',
      'portal_migration':'Upgrades to newer Plone versions',
      'portal_registration':'Handles registration of new users',
      'portal_skins':'Controls skin behaviour (search order etc)',
      'portal_syndication':'Generates RSS for folders',
      'portal_workflow':'Contains workflow definitions for your portal',
      'portal_url':'Methods to anchor you to the root of your Plone site',
      'portal_discussion':'Controls how discussions are stored',
      'portal_catalog':'Indexes all content in the site',
      'portal_factory':'Responsible for the creation of content objects',
      'portal_calendar':'Controls how events are shown',
      'portal_quickinstaller':'Allows to install/uninstall products',
      'portal_interface':'Allows to query object interfaces',
      'portal_actionicons':'Associates actions with icons',
      'portal_groupdata':'Handles properties on groups',
      'portal_groups':'Handles group related functionality',
      'translation_service': 'Provides access to the translation machinery',
      'mimetypes_registry': 'MIME types recognized by Plone',
      'portal_transforms': 'Handles data conversion between MIME types',
      }
 
     for oid in portal.objectIds():
         title=titles.get(oid, None)
         if title:
             setattr(aq_get(portal, oid), 'title', title)
     out.append('Assigned titles to portal tools.')
Esempio n. 8
0
    def pt_getContext(self, instance, request=None, **kw):
        namespace = super(ViewAwareZopePageTemplate, self).pt_getContext(**kw)
        namespace["request"] = request
        namespace["view"] = instance
        namespace["context"] = context = instance.context
        namespace["views"] = ViewMapper(context, request)

        # get the root
        obj = context
        root = None
        meth = aq_get(obj, "getPhysicalRoot", None)
        if meth is not None:
            root = meth()

        namespace.update(
            here=obj,
            # philiKON thinks container should be the view,
            # but BBB is more important than aesthetics.
            container=obj,
            root=root,
            modules=SecureModuleImporter,
            traverse_subpath=[],  # BBB, never really worked
            user=getSecurityManager().getUser(),
        )
        return namespace
Esempio n. 9
0
def sendInvitationMail(site, member, vars):
    request = aq_get(site, 'REQUEST')
    fullname = member.getProperty('fullname') or member.getId()
    hostname = request.other['SERVER_URL']
    invite_to_address = vars['invite_to_address']
    invitecode = vars['invitecode']
    message = vars['message']

    tool = getToolByName(site, 'portal_invitations')
    expires = DateTime() + tool.getProperty('days', 7)

    accept_url = '%s/accept/%s?email=%s' % (
        site.absolute_url(), quote(invitecode), quote(invite_to_address))

    mail_text = InvitationMail(site, request)(member=member,
        email=invite_to_address, sender_fullname=fullname, hostname=hostname,
        message=message, expires=expires, accept_url=accept_url)
    if isinstance(mail_text, unicode):
        mail_text = mail_text.encode('utf-8')

    message_obj = message_from_string(mail_text.strip())
    subject = message_obj['Subject']
    m_to = message_obj['To']
    m_from = message_obj['From']

    host = getToolByName(site, 'MailHost')
    host.send(mail_text, m_to, m_from, subject=subject,
              charset='utf-8', immediate=True)
def createExprContext(folder, portal, object):
    """
    An expression context provides names for TALES expressions.
    """
    try:
        mtool = getUtility(IMembershipTool)
    except ComponentLookupError:
        # BBB: fallback for CMF 2.2 instances
        mtool = aq_get(portal, 'portal_membership')
    if object is None:
        object_url = ''
    else:
        object_url = object.absolute_url()
    if mtool.isAnonymousUser():
        member = None
    else:
        member = mtool.getAuthenticatedMember()
    data = {
        'object_url':   object_url,
        'folder_url':   folder.absolute_url(),
        'portal_url':   portal.absolute_url(),
        'object':       object,
        'folder':       folder,
        'portal':       portal,
        'nothing':      None,
        'request':      getattr(portal, 'REQUEST', None),
        'modules':      SecureModuleImporter,
        'member':       member,
        'here':         object,
        }
    return getEngine().getContext(data)
def getExprContext(context, object=None):
    request = getRequest()
    if request:
        cache = request.get('_ec_cache', None)
        if cache is None:
            request['_ec_cache'] = cache = {}
        ec = cache.get(id(object), None)
    else:
        ec = None
    if ec is None:
        try:
            utool = getUtility(IURLTool)
        except ComponentLookupError:
            # BBB: fallback for CMF 2.2 instances
            utool = aq_get(context, 'portal_url')
        portal = utool.getPortalObject()
        if object is None or not hasattr(object, 'aq_base'):
            folder = portal
        else:
            folder = object
            # Search up the containment hierarchy until we find an
            # object that claims it's a folder.
            while folder is not None:
                if getattr(aq_base(folder), 'isPrincipiaFolderish', 0):
                    # found it.
                    break
                else:
                    folder = aq_parent(aq_inner(folder))
        ec = createExprContext(folder, portal, object)
        if request:
            cache[id(object)] = ec
    return ec
Esempio n. 12
0
def referenceRemoved(obj, event, toInterface=IContactContent):
    """Store information about the removed link integrity reference.
    """
    # inspired from z3c/relationfield/event.py:breakRelations
    # and plone/app/linkintegrity/handlers.py:referenceRemoved
    # if the object the event was fired on doesn't have a `REQUEST` attribute
    # we can safely assume no direct user action was involved and therefore
    # never raise a link integrity exception...
    request = aq_get(obj, 'REQUEST', None)
    if not request:
        return
    storage = ILinkIntegrityInfo(request)

    catalog = component.queryUtility(ICatalog)
    intids = component.queryUtility(IIntIds)
    if catalog is None or intids is None:
        return

    # find all relations that point to us
    obj_id = intids.queryId(obj)
    if obj_id is None:
        return

    rels = list(catalog.findRelations({'to_id': obj_id}))
    for rel in rels:
        if toInterface.providedBy(rel.to_object):
            storage.addBreach(rel.from_object, rel.to_object)
Esempio n. 13
0
    def _edit( self, remote_url ):
        """
        Edit the Favorite. Unlike Links, Favorites have URLs that are
        relative to the root of the site.
        """
        # strip off scheme and machine from URL if present
        tokens = urlparse.urlparse( remote_url, 'http' )
        if tokens[1]:
            # There is a nethost, remove it
            t=('', '') + tokens[2:]
            remote_url=urlparse.urlunparse(t)
        # if URL begins with site URL, remove site URL
        utool = queryUtility(IURLTool)
        if utool is None:
            # fallback for bootstrap
            utool = aq_get(self, 'portal_url', None)
        portal_url = utool.getPortalPath()
        i = remote_url.find(portal_url)
        if i==0:
            remote_url=remote_url[len(portal_url):]
        # if site is still absolute, make it relative
        if remote_url[:1]=='/':
            remote_url=remote_url[1:]
        self.remote_url=remote_url

        # save unique id of favorite
        self.remote_uid = self._getUidByUrl()
Esempio n. 14
0
    def setPassword(self, password, domains=None, REQUEST=None):
        '''Allows the authenticated member to set his/her own password.
        '''
        registration = getToolByName(self, 'portal_registration', None)
        if not self.isAnonymousUser():
            member = self.getAuthenticatedMember()
            acl_users = self._findUsersAclHome(member.getUserId())#self.acl_users
            if not acl_users:
                # should not possibly ever happen
                raise BadRequest, 'did not find current user in any user folder'
            if registration:
                failMessage = registration.testPasswordValidity(password)
                if failMessage is not None:
                    raise BadRequest, failMessage

            if domains is None:
                domains = []
            user = acl_users.getUserById(member.getUserId(), None)
            # we must change the users password trough grufs changepassword
            # to keep her  group settings
            if hasattr(user, 'changePassword'):
                user.changePassword(password)
            else:
                acl_users._doChangeUser(member.getUserId(), password, member.getRoles(), domains)
            if REQUEST is None:
                REQUEST = aq_get(self, 'REQUEST', None)
            self.credentialsChanged(password, REQUEST=REQUEST)
        else:
            raise BadRequest, 'Not logged in.'
 def __call__(self, context):
     request = aq_get(context, "REQUEST", None)
     terms = [
         SimpleTerm(value, token, translate(title, domain="plone", context=request, default=default))
         for value, token, title, default in self.terms
     ]
     return SimpleVocabulary(terms)
Esempio n. 16
0
File: slot.py Progetto: goschtl/zope
def formatException(context, editing):
    """Returns an HTML-ified error message.

    If not editing, the message includes no details.
    """
    exc_info = sys.exc_info()
    try:
        if editing:
            # Show editors the real error
            t, v = exc_info[:2]
            t = getattr(t, '__name__', t)
            msg = "An error occurred. %s" % (
                escape(('%s: %s' % (t, v))[:80]))
        else:
            # Show viewers a simplified error.
            msg = ("An error occurred while generating "
                    "this part of the page.")
        try:
            log = aq_get(context, '__error_log__', None, 1)
        except AttributeError:
            LOG("Composite", ERROR, "Error in a page element",
                error=exc_info)
            return msg
        else:
            error_log_url = log.raising(exc_info)
            return error_tag % (msg, error_log_url)
    finally:
        del exc_info
Esempio n. 17
0
    def getRolesForPrincipal(self, principal, request=None):
        """ See IRolesPlugin.
        """
        roles = set([])
        principal_ids = set([])
        # Some services need to determine the roles obtained from groups
        # while excluding the directly assigned roles.  In this case
        # '__ignore_direct_roles__' = True should be pushed in the request.
        request = aq_get(self, 'REQUEST', None)
        if request is None \
           or not request.get('__ignore_direct_roles__', False):
            principal_ids.add(principal.getId())

        # Some services may need the real roles of an user but **not**
        # the ones he got through his groups. In this case, the
        # '__ignore_group_roles__'= True should be previously pushed
        # in the request.
        plugins = self._getPAS()['plugins']
        if request is None \
           or not request.get('__ignore_group_roles__', False):
            principal_ids.update(
                getGroupsForPrincipal(principal, plugins, request)
            )
        for pid in principal_ids:
            roles.update(self._principal_roles.get(pid, ()))
        return tuple(roles)
Esempio n. 18
0
def findObject(base, path):
    """ traverse to given path and find the upmost object """
    if path.startswith('/'):
        obj = getToolByName(base, 'portal_url').getPortalObject()
        portal_path = '/'.join(obj.getPhysicalPath())
        components = path.lstrip(portal_path + '/').split('/')
    else:
        obj = aq_parent(base)   # relative urls start at the parent...
        components = path.split('/')
    while components:
        child_id = unquote(components[0])
        try:
            try:
                child = obj.unrestrictedTraverse(child_id)
            except AttributeError:
                request = aq_get(obj, 'REQUEST')
                child = request.traverseName(obj, child_id)
        except ConflictError:
            raise
        except (AttributeError, KeyError, NotFound, ztkNotFound):
            return None, None
        if not IItem.providedBy(child):
            break
        obj = child
        components.pop(0)
    return obj, '/'.join(components)
def getObject(self, REQUEST=None):
    path = self.getPath().split('/')
    if not path:
        return None
    parent = aq_parent(self)
    if (aq_get(parent, 'REQUEST', None) is None
        and _GLOBALREQUEST_INSTALLED and _REQUESTCONTAINER_EXISTS):
        request = getRequest()
        if request is not None:
            # path should be absolute, starting at the physical root
            parent = self.getPhysicalRoot()
            request_container = RequestContainer(REQUEST=request)
            parent = aq_base(parent).__of__(request_container)
    if len(path) > 1:
        try:
            parent = parent.unrestrictedTraverse(path[:-1])
        except:
            if path[:-2] == 'data-'+self.portal_type:
                parent = queryMultiAdapter((None, ICollectiveBehaviorSQLLayer), IBrowserView, name='data-'+name, default=None)
    try:
        return parent.restrictedTraverse(path[-1])
    except:
        connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None)
        if connection == None and self.portal_type:
            fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None)
            if not fti:
                return None
            updateConnectionsForFti(fti)
            connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None)
        return connection.getVirtualItem(self.sql_id, context=parent)
    def getObject(self, REQUEST=None):
        """Return the object for this record

        Will return None if the object cannot be found via its cataloged path
        (i.e., it was deleted or moved without recataloging), or if the user is
        not authorized to access the object.

        This method mimicks a subset of what publisher's traversal does,
        so it allows access if the final object can be accessed even
        if intermediate objects cannot.
        """
        path = self.getPath().split('/')
        if not path:
            return None
        parent = aq_parent(self)
        if (aq_get(parent, 'REQUEST', None) is None
            and _GLOBALREQUEST_INSTALLED and _REQUESTCONTAINER_EXISTS):
            request = getRequest()
            if request is not None:
                # path should be absolute, starting at the physical root
                parent = self.getPhysicalRoot()
                request_container = RequestContainer(REQUEST=request)
                parent = aq_base(parent).__of__(request_container)
        if len(path) > 1:
            parent = parent.unrestrictedTraverse(path[:-1])

        return parent.restrictedTraverse(path[-1])
Esempio n. 21
0
    def __call__(self, context):
        site = getSite()
        wtool = getToolByName(site, 'portal_workflow', None)
        if wtool is None:
            return SimpleVocabulary([])

        transitions = {}
        for wf in wtool.values():
            transition_folder = getattr(wf, 'transitions', None)
            wf_name = wf.title or wf.id
            if transition_folder is not None:
                for transition in transition_folder.values():
                    transition_title = translate(
                                        _(transition.actbox_name),
                                        context=aq_get(wtool, 'REQUEST', None))
                    transitions.setdefault(transition.id, []).append(
                        dict(title=transition_title, wf_name=wf_name))
        items = []
        transition_items = transitions.items()
        transition_items.sort(key=lambda transition: transition[0])
        for transition_id, info in transition_items:
            titles = set([i['title'] for i in info])
            item_title = ' // '.join(sorted(titles))
            item_title = "%s [%s]" % (item_title, transition_id)
            items.append(SimpleTerm(transition_id, transition_id, item_title))

        return SimpleVocabulary(items)
Esempio n. 22
0
    def getOwnerTuple(self):
        """Return a tuple, (userdb_path, user_id) for the owner.

        o Ownership can be acquired, but only from the containment path.

        o If unowned, return None.
        """
        return aq_get(self, '_owner', None, 1)
Esempio n. 23
0
 def pt_getContext(self, *args, **kw):
     root = None
     meth = aq_get(self, 'getPhysicalRoot', None)
     if meth is not None:
         root = meth()
     context = self._getContext()
     c = {'template': self,
          'here': context,
          'context': context,
          'container': self._getContainer(),
          'nothing': None,
          'options': {},
          'root': root,
          'request': aq_get(root, 'REQUEST', None),
          'modules': SecureModuleImporter,
          }
     return c
Esempio n. 24
0
 def getUI(self, ui=None):
     """Returns a UI object.
     """
     if not ui:
         ui = self.default_ui
     tool = aq_get(self, "composite_tool", None, 1)
     if tool is None:
         raise CompositeError("No composite_tool found")
     return guarded_getattr(tool.uis, ui)
Esempio n. 25
0
 def test_mail_setup(self):
     portal = self.layer['portal']
     name = portal.getProperty('email_from_name')
     self.assertNotEquals(name, '')
     address = portal.getProperty('email_from_address')
     self.assertNotEquals(address, '')
     mailhost = aq_get(portal, 'MailHost')
     self.assertNotEquals(mailhost.smtp_host, '')
     self.assertNotEquals(mailhost.smtp_port, '')
    def translate(self, msgid, domain=None, mapping=None, context=None,
                  target_language=None, default=None):
        # Translate method for resticted code like skins.
        if context is not None:
            if not IBrowserRequest.providedBy(context):
                context = aq_get(context, 'REQUEST', None)

        return translate(msgid, domain=domain, mapping=mapping,
                         context=context, target_language=target_language,
                         default=default)
 def getGroups(self):
     gf = aq_get(self.context, "__allow_groups__", None, 1)
     if gf is None:
         return ()
     try:
         groups = gf.searchGroups()
     except AttributeError:
         return ()
     else:
         return groups
Esempio n. 28
0
 def translate(self, domain, msgid, context=None, **kw):
     translate = self.getTranslateMethod(context, domain)
     
     # For zope.i18n, the 'context' of a translation request is actually the
     # an IBrowserRequest, for languate negotiation (see, for instance,
     # Products.CMFPlone.TranslationServiceTool). The new localizer
     # MessageCatalog abides by the zope.i18n.interface definitions.
     # (Actually, it ignores the context).
     request = aq_get(context, 'REQUEST', None)
     return translate(msgid=msgid, context=request, **kw)
Esempio n. 29
0
    def manage_changeOwnershipType(self, explicit=1,
                                   RESPONSE=None, REQUEST=None):
        """Change the type (implicit or explicit) of ownership.
        """
        old=getattr(self, '_owner', None)
        if explicit:
            if old is not None: return
            owner=aq_get(self, '_owner', None, 1)
            if owner is not None and owner is not UnownableOwner:
                self._owner=owner
        else:
            if old is None: return
            new=aq_get(aq_parent(self), '_owner', None, 1)
            if old is new and (
                self.__dict__.get('_owner', _mark) is not _mark
                ):
                del self._owner

        if RESPONSE is not None: RESPONSE.redirect(REQUEST['HTTP_REFERER'])
Esempio n. 30
0
def getEmptyTitle(context, translated=True):
    """Returns string to be used for objects with no title or id"""
    # The default is an extra fancy unicode elipsis
    empty = unicode("\x5b\xc2\xb7\xc2\xb7\xc2\xb7\x5d", "utf-8")
    if translated:
        if context is not None:
            if not IBrowserRequest.providedBy(context):
                context = aq_get(context, "REQUEST", None)
        empty = translate("title_unset", domain="plone", context=context, default=empty)
    return empty
    def fVerifyOrInitialize_ExternalMethod(self,
                                           theInitializationSpecification=None,
                                           theContextualElement=None,
                                           theAllowInitialization=False,
                                           thePortalRoot=None):

        if not theInitializationSpecification:
            return None

        if theContextualElement == None:
            return None

        if thePortalRoot == None:
            return None

        unInforme = self.fNewVoidInformeVerifyOrInitExternalMethod()

        aExtMethodModule = theInitializationSpecification.get(
            'ext_method_module', '')
        aExtMethodFunction = theInitializationSpecification.get(
            'ext_method_function', '')
        aExtMethodId = theInitializationSpecification.get('ext_method_id', '')
        aExtMethodTitle = theInitializationSpecification.get(
            'ext_method_title', '')
        anInstallPath = theInitializationSpecification.get('install_path', '')
        aRequired = theInitializationSpecification.get('required', '')

        try:
            unInforme.update({
                'ext_method_module': aExtMethodModule,
                'ext_method_function': aExtMethodFunction,
                'ext_method_id': aExtMethodId,
                'ext_method_title': aExtMethodTitle,
                'install_path': anInstallPath,
                'required': aRequired,
            })

            if not aExtMethodModule or not aExtMethodFunction or not aExtMethodId or not aExtMethodTitle:
                unInforme['success'] = False
                unInforme['condition'] = 'MISSING_parameters'
                return unInforme

            if theAllowInitialization:
                if not self.fCheckInitializationPermissions_ExternalMethod(
                        theContextualElement):
                    unInforme['success'] = False
                    unInforme[
                        'condition'] = 'user_can_NOT_initialize ExternalMethod %s' % str(
                            theInitializationSpecification)
                    return unInforme

            unInstallContainer = thePortalRoot

            if anInstallPath:
                unInstallContainer = self.fInstallContainer_Traversal(
                    thePortalRoot, anInstallPath)

            if unInstallContainer == None:
                unInforme.update({
                    'success': False,
                    'condition': 'No_InstallContainer',
                })
                return unInforme

            unExternalMethod = None
            try:
                unExternalMethod = aq_get(unInstallContainer, aExtMethodId,
                                          None, 1)
            except:
                None
            if unExternalMethod:
                unInforme['success'] = True
                unInforme['status'] = 'exists'
                return unInforme

            if not (theAllowInitialization and cLazyCreateExternalMethods):
                unInforme['success'] = False
                unInforme['status'] = 'missing'
                return unInforme

            unNewExternalMethod = None
            try:
                unNewExternalMethod = ExternalMethod(
                    aExtMethodId,
                    aExtMethodTitle,
                    aExtMethodModule,
                    aExtMethodFunction,
                )
            except:
                unaExceptionInfo = sys.exc_info()
                unaExceptionFormattedTraceback = ''.join(
                    traceback.format_exception(*unaExceptionInfo))

                unInformeExcepcion = 'Exception during ExternalMethod compilation in operation fVerifyOrInitialize_ExternalMethod for %s\n' % str(
                    theInitializationSpecification)
                unInformeExcepcion += 'exception class %s\n' % unaExceptionInfo[
                    1].__class__.__name__
                unInformeExcepcion += 'exception message %s\n\n' % str(
                    unaExceptionInfo[1].args)
                unInformeExcepcion += unaExceptionFormattedTraceback

                unInforme['success'] = False
                unInforme['condition'] = 'exception'
                unInforme['exception'] = unInformeExcepcion

                if cLogExceptions:
                    logging.getLogger('ModelDDvlPloneTool').error(
                        unInformeExcepcion)

                return unInforme

            if not unNewExternalMethod:
                unInforme['success'] = False
                unInforme['status'] = 'creation_failed'
                return unInforme

            unInstallContainer._setObject(aExtMethodId, unNewExternalMethod)
            unExternalMethod = None
            try:
                unExternalMethod = aq_get(unInstallContainer, aExtMethodId,
                                          None, 1)
            except:
                None
            if not unExternalMethod:
                unInforme['success'] = False
                unInforme['status'] = 'creation_failed'
                return unInforme

            unInforme['success'] = True
            unInforme['status'] = 'created'

            transaction.commit()
            unInforme['committed'] = True

            return unInforme

        except:
            unaExceptionInfo = sys.exc_info()
            unaExceptionFormattedTraceback = ''.join(
                traceback.format_exception(*unaExceptionInfo))

            unInformeExcepcion = 'Exception during Lazy Initialization operation fVerifyOrInitialize_ExternalMethod %s\n' % str(
                theInitializationSpecification)
            unInformeExcepcion += 'exception class %s\n' % unaExceptionInfo[
                1].__class__.__name__
            unInformeExcepcion += 'exception message %s\n\n' % str(
                unaExceptionInfo[1].args)
            unInformeExcepcion += unaExceptionFormattedTraceback

            unInforme['success'] = False
            unInforme['condition'] = 'exception'
            unInforme['exception'] = unInformeExcepcion

            if cLogExceptions:
                logging.getLogger('ModelDDvlPloneTool').error(
                    unInformeExcepcion)

            return unInforme
Esempio n. 32
0
 def get(self, field):
     accessor = field.getAccessor(self.context)
     if accessor:
         return accessor()
     else:
         return aq_get(self.context, field.id, None)
Esempio n. 33
0
 def __call__(self, context):
     request = aq_get(context, 'REQUEST', None)
     terms = [SimpleTerm(value, token, translate(title, domain="plone", context=request, default=default)) for value, token, title, default in self.terms]
     return SimpleVocabulary(terms)
    def _apply_index(self, request, resultset=None):
        """
            Apply the index to query parameters given in 'request', which
            should be a mapping object.

            If the request does not contain the needed parameters, then
            return None.

            Otherwise return two objects.  The first object is a ResultSet
            containing the record numbers of the matching records.  The
            second object is a tuple containing the names of all data fields
            used.
        """
        iid = self.id
        record = parseIndexRequest(request, iid, self.query_options)
        if record.keys is None:
            return None

        term = self._convertDateTime(record.keys[0])
        REQUEST = aq_get(self, 'REQUEST', None)
        if REQUEST is not None:
            catalog = aq_parent(aq_parent(aq_inner(self)))
            if catalog is not None:
                key = self._cache_key(catalog)
                cache = REQUEST.get(key, None)
                tid = isinstance(term, int) and term / 10 or 'None'
                if resultset is None:
                    cachekey = '_daterangeindex_%s_%s' % (iid, tid)
                else:
                    cachekey = '_daterangeindex_inverse_%s_%s' % (iid, tid)
                if cache is None:
                    cache = REQUEST[key] = RequestCache()
                else:
                    cached = cache.get(cachekey, None)
                    if cached is not None:
                        if resultset is None:
                            return (cached, (self._since_field,
                                             self._until_field))
                        else:
                            return (difference(resultset, cached),
                                    (self._since_field, self._until_field))

        if resultset is None:
            # Aggregate sets for each bucket separately, to avoid
            # large-small union penalties.
            until_only = multiunion(self._until_only.values(term))
            since_only = multiunion(self._since_only.values(None, term))
            until = multiunion(self._until.values(term))

            # Total result is bound by resultset
            if REQUEST is None:
                until = intersection(resultset, until)

            since = multiunion(self._since.values(None, term))
            bounded = intersection(until, since)

            # Merge from smallest to largest.
            result = multiunion(
                [bounded, until_only, since_only, self._always])
            if REQUEST is not None and catalog is not None:
                cache[cachekey] = result

            return (result, (self._since_field, self._until_field))
        else:
            # Compute the inverse and subtract from res
            until_only = multiunion(self._until_only.values(None, term - 1))
            since_only = multiunion(self._since_only.values(term + 1))
            until = multiunion(self._until.values(None, term - 1))
            since = multiunion(self._since.values(term + 1))

            result = multiunion([until_only, since_only, until, since])
            if REQUEST is not None and catalog is not None:
                cache[cachekey] = result

            return (difference(resultset,
                               result), (self._since_field, self._until_field))
Esempio n. 35
0
 def wtool(self):
     try:
         return getUtility(IWorkflowTool)
     except ComponentLookupError:
         # BBB: fallback for CMF 2.2 instances
         return aq_get(self.context, 'portal_workflow')
Esempio n. 36
0
def get_installer(context, request=None):
    if request is None:
        request = aq_get(context, 'REQUEST', None)
    view = getMultiAdapter((context, request), name='installer')
    return view
Esempio n. 37
0
 def __bobo_traverse__(self, request, name):
     from Acquisition import aq_get
     return aq_get(self, name)
Esempio n. 38
0
def managersExist(ob):
    # Returns 1 if any CacheManagers exist in the context of ob.
    if aq_get(ob, ZCM_MANAGERS, None, 1):
        return 1
    return 0
Esempio n. 39
0
    def installProduct(self, p, locked=False, hidden=False,
                       swallowExceptions=None, reinstall=False,
                       forceProfile=False, omitSnapshots=True,
                       profile=None, blacklistedSteps=None):
        """Install a product by name
        """
        __traceback_info__ = (p, )

        if profile is not None:
            forceProfile = True

        if self.isProductInstalled(p):
            prod = self._getOb(p)
            msg = ('This product is already installed, '
                   'please uninstall before reinstalling it.')
            prod.log(msg)
            return msg

        portal = aq_parent(aq_inner(self))

        before = self.snapshotPortal(portal)

        if hasattr(self, "REQUEST"):
            reqstorage = IAnnotatable(self.REQUEST, None)
            if reqstorage is not None:
                installing = reqstorage.get("Products.CMFQUickInstaller.Installing", set())
                installing.add(p)
        else:
            reqstorage = None

        # XXX We can not use getToolByName since that returns a utility
        # without a RequestContainer. This breaks import steps that need
        # to run tools which request self.REQUEST.
        portal_setup = aq_get(portal, 'portal_setup', None, 1)
        status = None
        res = ''

        # Create a snapshot before installation
        before_id = portal_setup._mangleTimestampName('qi-before-%s' % p)
        if not omitSnapshots:
            portal_setup.createSnapshot(before_id)

        install = False
        if not forceProfile:
            try:
                # Install via external method
                install = self.getInstallMethod(p).__of__(portal)
            except AttributeError:
                # No classic install method found
                pass

        if install and not forceProfile:
            try:
                res = install(portal, reinstall=reinstall)
            except TypeError:
                res = install(portal)
            status = 'installed'
        else:
            profiles = self.getInstallProfiles(p)
            if profiles:
                if profile is None:
                    profile = profiles[0]
                    if len(profiles) > 1:
                        logger.log(logging.INFO,
                                   'Multiple extension profiles found for product '
                                   '%s. Used profile: %s' % (p, profile))

                portal_setup.runAllImportStepsFromProfile(
                    'profile-%s' % profile,
                    blacklisted_steps=blacklistedSteps,
                )
                status = 'installed'
            else:
                # No install method and no profile, log / abort?
                pass

        if reqstorage is not None:
            installing.remove(p)

        # Create a snapshot after installation
        after_id = portal_setup._mangleTimestampName('qi-after-%s' % p)
        if not omitSnapshots:
            portal_setup.createSnapshot(after_id)

        if profile:
            # If installation was done via a profile, the settings were already
            # snapshotted in the IProfileImportedEvent handler, and we should
            # use those because the ones derived here include settings from
            # dependency profiles.
            settings = {}
        else:
            after = self.snapshotPortal(portal)
            settings = self.deriveSettingsFromSnapshots(before, after)

        rr_css = getToolByName(self, 'portal_css', None)
        if rr_css is not None:
            if 'resources_css' in settings and len(settings['resources_css']) > 0:
                rr_css.cookResources()

        msg = str(res)
        version = self.getProductVersion(p)

        # add the product
        self.notifyInstalled(
            p,
            settings=settings,
            installedversion=version,
            logmsg=res,
            status=status,
            error=False,
            locked=locked,
            hidden=hidden,
            afterid=after_id,
            beforeid=before_id)

        prod = getattr(self, p)
        afterInstall = prod.getAfterInstallMethod()
        if afterInstall is not None:
            afterInstall = afterInstall.__of__(portal)
            afterRes = afterInstall(portal, reinstall=reinstall, product=prod)
            if afterRes:
                res = res + '\n' + str(afterRes)
        return res
Esempio n. 40
0
def store_on_request(method, self, user, obj, object_roles):
    """ helper for caching local roles on the request """
    return IAnnotations(aq_get(obj, 'REQUEST'))
Esempio n. 41
0
 def getURL(self, relative=0):
     request = aq_get(self._catalog, 'REQUEST', None)
     if request is None:
         request = getRequest()
     return request.physicalPathToURL(self.getPath(), relative)
Esempio n. 42
0
 def atool(self):
     try:
         return getUtility(IActionsTool)
     except ComponentLookupError:
         # BBB: fallback for CMF 2.2 instances
         return aq_get(self.context, 'portal_actions')
Esempio n. 43
0
 def mtool(self):
     try:
         return getUtility(IMembershipTool)
     except ComponentLookupError:
         # BBB: fallback for CMF 2.2 instances
         return aq_get(self.context, 'portal_membership')
Esempio n. 44
0
 def setUpZope(self, app, configurationContext):
     request = aq_get(app, 'REQUEST')
     request.environ['HTTP_ACCEPT_LANGUAGE'] = 'de'
     self.loadZCML(package=operun.crm)
     self.loadZCML(package=plone.session)
     z2.installProduct(app, 'plone.session')
Esempio n. 45
0
 def utool(self):
     try:
         return getUtility(IURLTool)
     except ComponentLookupError:
         # BBB: fallback for CMF 2.2 instances
         return aq_get(self.context, 'portal_url')
Esempio n. 46
0
def enable_secure_cookies(context):
    acl = aq_get(context, 'acl_users')
    acl.session._updateProperty('secure', True)
    acl.session._updateProperty('timeout', 172800)
    acl.session._updateProperty('refresh_interval', 7200)
    acl.session._updateProperty('cookie_lifetime', 7)
Esempio n. 47
0
 def __init__(self, obj):
     self._realobject = obj
     self.request = aq_get(obj, 'REQUEST')
Esempio n. 48
0
 def safe_call(self):
     return aq_get(aq_parent(self.context), 'Title')()
Esempio n. 49
0
def _isNotBeingUsedAsAMethod(self):
    return not aq_get(self, '_isBeingUsedAsAMethod_', 0)
Esempio n. 50
0
 def safe_call(self):
     return aq_get(aq_parent(self.context), 'absolute_url')()
Esempio n. 51
0
 def __init__(self, brain):
     self._brain = brain
     self._cached_realobject = None
     self.request = aq_get(brain, 'REQUEST')
Esempio n. 52
0
def clra_cache_key(method, self, user, obj, object_roles):
    """ The cache key needs to include all arguments when caching allowed
        local roles, but the key function also needs to decide whether
        `volatile.cache` can cache or not by checking if it's possible to
        get a request instance from the object.

        To test we'll nee an adaptable object, a user and the method which
        results' we'd like to cache:

          >>> from zope.interface import implements, Interface
          >>> class DummyObject(object):
          ...     implements(Interface)
          >>> obj = DummyObject()

          >>> from borg.localrole.tests import DummyUser
          >>> john = DummyUser('john')

          >>> rm = WorkspaceLocalRoleManager('rm', 'A Role Manager')
          >>> fun = rm.__class__.checkLocalRolesAllowed

        The dummy object doesn't have an acquired request, so no caching
        can be done:

          >>> clra_cache_key(fun, 'me', john, obj, ['foo', 'bar'])
          Traceback (most recent call last):
          ...
          DontCache

        So let's add one and try again.  Before we also need to mark it as
        being annotatable, which normally happens elsewhere:

          >>> from ZPublisher.HTTPRequest import HTTPRequest
          >>> request = HTTPRequest('', dict(HTTP_HOST='nohost:8080'), {})

          >>> from Products.Five.zcml import load_config
          >>> import zope.component
          >>> import zope.annotation
          >>> load_config('meta.zcml', zope.component)
          >>> load_config('configure.zcml', zope.annotation)
          >>> from zope.interface import classImplements
          >>> from zope.annotation.interfaces import IAttributeAnnotatable
          >>> classImplements(HTTPRequest, IAttributeAnnotatable)

          >>> obj.REQUEST = request
          >>> clra_cache_key(fun, 'hmm', john, obj, ['foo', 'bar'])
          ('john', ..., ('foo', 'bar'))

        If the objects happens to have a `getPhysicalPath` method, that should
        be used instead of the hash:

          >>> class DummyObjectWithPath(DummyObject):
          ...     def getPhysicalPath(self):
          ...         return '42!'
          >>> obj = DummyObjectWithPath()
          >>> obj.REQUEST = request
          >>> clra_cache_key(fun, 'hmm', john, obj, ['foo', 'bar'])
          ('john', '42!', ('foo', 'bar'))

        Now let's check if the results of a call to `checkLocalRolesAllowed`
        is indeed cached, i.e. is the request was annotated correctly.  First
        try to log the method invocation, though.  As monkey patching in
        something between the original method and the already applied cache
        decorator is tricky, we abuse `_get_userfolder`, which is called
        first thing in `checkLocalRolesAllowed`:

          >>> original = rm._get_userfolder
          >>> def logger(self, *args, **kw):
          ...     print 'checkLocalRolesAllowed called...'
          ...     return original(self, *args, **kw)
          >>> rm._get_userfolder = logger

          >>> print rm.checkLocalRolesAllowed(john, obj, ['foo', 'bar'])
          checkLocalRolesAllowed called...
          None
          >>> IAnnotations(request)
          {"borg.localrole.workspace.checkLocalRolesAllowed:('john', '42!', ('foo', 'bar'))": None}

        Calling the method a second time should directly return the cached
        value, i.e. the logger shouldn't print anything:

          >>> print rm.checkLocalRolesAllowed(john, obj, ['foo', 'bar'])
          None

    """
    request = aq_get(obj, 'REQUEST', None)
    if IAnnotations(request, None) is None:
        raise DontCache
    try:
        oid = obj.getPhysicalPath()
    except AttributeError:
        oid = id(obj)
    return (user.getId(), oid, tuple(object_roles))
def search_value_in_objects(s_obj, ref, p_types=[], type_fields={}):
    """
        Searching a value (reference to an object like id or uid) in fields of objects.
        Parameters:
            * s_obj : the object that is maybe referenced in another objects fields
            * ref : the value to search in field
            * p_types : portal_types that will be only searched
            * type_fields : dict containing as key portal_type and as value a list of fields that must be searched.
                            If a portal_type is not given, all fields will be searched
    """
    # we check all dexterity objects fields to see if ref is used in
    # we can't check only fields using plonegroup vocabulary because maybe another vocabulary name is used
    # this can be long but this operation is not made so often

    request = aq_get(s_obj, 'REQUEST', None)
    if not request:
        return
    try:
        catalog = api.portal.get_tool('portal_catalog')
    except api.portal.CannotGetPortalError:
        # When deleting site, the portal is no more found...
        return

    storage = ILinkIntegrityInfo(request)

    def list_fields(ptype, filter_interfaces=(IText, ICollection, IChoice)):
        """ return for the portal_type the selected fields """
        if ptype not in type_fields:
            type_fields[ptype] = []
            fti = getUtility(IDexterityFTI, name=ptype)
            for name, fld in getFieldsInOrder(fti.lookupSchema()):
                for iface in filter_interfaces:
                    if iface.providedBy(fld):
                        type_fields[ptype].append(name)
                        break
            # also lookup behaviors
            for behavior_id in fti.behaviors:
                behavior = getUtility(IBehavior, behavior_id).interface
                for name, fld in getFieldsInOrder(behavior):
                    for iface in filter_interfaces:
                        if iface.providedBy(fld):
                            type_fields[ptype].append(name)
                            break
        return type_fields[ptype]

    def check_value(val):
        if isinstance(val, basestring) and val == ref:
            return True
        return False

    def check_attribute(val):
        """ check the attribute value and walk in it """
        if isinstance(val, dict):
            for v in val.values():
                res = check_attribute(v)
                if res:
                    return res
        elif base_hasattr(val, '__iter__'):
            for v in val:
                res = check_attribute(v)
                if res:
                    return res
        elif check_value(val):
            res = [val]
            return res
        return []

    for brain in catalog.unrestrictedSearchResults(
            portal_types=p_types,
            object_provides=IDexterityContent.__identifier__):
        obj = brain._unrestrictedGetObject()
        ptype = obj.portal_type
        for attr in list_fields(ptype):
            if base_hasattr(obj, attr):
                res = check_attribute(getattr(obj, attr))
                if res:
                    storage.addBreach(obj, s_obj)
                    break
Esempio n. 54
0
def boost_values(obj, data):
    """ calculate boost values using a method or skin script;  returns
        a dictionary with the values or `None` """
    boost_index_getter = aq_get(obj, 'solr_boost_index_values', None)
    if boost_index_getter is not None:
        return boost_index_getter(data)
    def fVerifyOrInitialize_ToolSingleton(self,
                                          theInitializationSpecification=None,
                                          theContextualElement=None,
                                          theAllowInitialization=False,
                                          thePortalRoot=None):

        if not theInitializationSpecification:
            return None

        if theContextualElement == None:
            return None

        if thePortalRoot == None:
            return None

        unInforme = self.fNewVoidInformeVerifyOrInitToolSingleton()

        aSingletonId = theInitializationSpecification.get('singleton_id', '')
        aToolModule = theInitializationSpecification.get('tool_module', '')
        aToolClassName = theInitializationSpecification.get('tool_class', '')
        anInstallPath = theInitializationSpecification.get('install_path', '')
        aRequired = theInitializationSpecification.get('required', '')

        try:
            unInforme.update({
                'singleton_id': aSingletonId,
                'tool_module': aToolModule,
                'tool_class': aToolClassName,
                'install_path': anInstallPath,
                'required': aRequired,
            })

            if not aSingletonId or not aToolModule or not aToolClassName:
                unInforme['success'] = False
                unInforme['condition'] = 'MISSING_parameters'
                return unInforme

            if theAllowInitialization:
                if not self.fCheckInitializationPermissions_ToolSingleton(
                        theContextualElement):
                    unInforme['success'] = False
                    unInforme[
                        'condition'] = 'user_can_NOT_initialize ToolSingleton %s' % str(
                            theInitializationSpecification)
                    return unInforme

            unInstallContainer = thePortalRoot

            if anInstallPath:
                unInstallContainer = self.fInstallContainer_Traversal(
                    thePortalRoot, anInstallPath)

            if unInstallContainer == None:
                unInforme.update({
                    'success': False,
                    'condition': 'No_InstallContainer',
                })
                return unInforme

            unToolSingleton = None
            try:
                unToolSingleton = aq_get(unInstallContainer, aSingletonId,
                                         None, 1)
            except:
                None
            if unToolSingleton:
                unInforme['success'] = True
                unInforme['status'] = 'exists'
                return unInforme

            if not (theAllowInitialization and cLazyCreateToolSingletons):
                unInforme['success'] = False
                unInforme['status'] = 'missing'
                return unInforme

            unToolClass = self.fPackageClass_Traversal(aToolModule,
                                                       aToolClassName)
            if not unToolClass:
                unInforme['success'] = False
                unInforme['status'] = 'ClassNotFound'
                return unInforme

            unNewToolSingleton = None
            try:
                unNewToolSingleton = unToolClass()
            except:
                unaExceptionInfo = sys.exc_info()
                unaExceptionFormattedTraceback = ''.join(
                    traceback.format_exception(*unaExceptionInfo))

                unInformeExcepcion = 'Exception during Singleton instantiation in operation fVerifyOrInitialize_ToolSingleton for %s\n' % str(
                    theInitializationSpecification)
                unInformeExcepcion += 'exception class %s\n' % unaExceptionInfo[
                    1].__class__.__name__
                unInformeExcepcion += 'exception message %s\n\n' % str(
                    unaExceptionInfo[1].args)
                unInformeExcepcion += unaExceptionFormattedTraceback

                unInforme['success'] = False
                unInforme['condition'] = 'exception'
                unInforme['exception'] = unInformeExcepcion

                unExecutionRecord and unExecutionRecord.pRecordException(
                    unInformeExcepcion)

                if cLogExceptions:
                    logging.getLogger('ModelDDvlPloneTool').error(
                        unInformeExcepcion)

                return unInforme

            if unNewToolSingleton == None:
                unInforme['success'] = False
                unInforme['status'] = 'creation_failed'
                return unInforme

            unInstallContainer._setObject(aSingletonId, unNewToolSingleton)
            unToolSingleton = None
            try:
                unToolSingleton = aq_get(unInstallContainer, aSingletonId,
                                         None, 1)
            except:
                None
            if not unToolSingleton:
                unInforme['success'] = False
                unInforme['status'] = 'creation_failed'
                return unInforme

            unInforme['success'] = True
            unInforme['status'] = 'created'

            transaction.commit()
            unInforme['committed'] = True

            return unInforme

        except:
            unaExceptionInfo = sys.exc_info()
            unaExceptionFormattedTraceback = ''.join(
                traceback.format_exception(*unaExceptionInfo))

            unInformeExcepcion = 'Exception during Lazy Initialization operation fVerifyOrInitialize_ToolSingleton %s\n' % str(
                theInitializationSpecification)
            unInformeExcepcion += 'exception class %s\n' % unaExceptionInfo[
                1].__class__.__name__
            unInformeExcepcion += 'exception message %s\n\n' % str(
                unaExceptionInfo[1].args)
            unInformeExcepcion += unaExceptionFormattedTraceback

            unInforme['success'] = False
            unInforme['condition'] = 'exception'
            unInforme['exception'] = unInformeExcepcion

            if cLogExceptions:
                logging.getLogger('ModelDDvlPloneTool').error(
                    unInformeExcepcion)

            return unInforme
Esempio n. 56
0
def ownableFilter(self):
    _owner = aq_get(self, '_owner', None, 1)
    return _owner is not UnownableOwner
Esempio n. 57
0
def _getVersionComment(object):
    request = aq_get(object, 'REQUEST', None)
    return request and request.get('cmfeditions_version_comment', '')