[Zope-Perl] Perl External Methods
Chris McDonough
chrism@digicool.com
Sun, 11 Jun 2000 16:16:21 -0400
Gisle Aas wrote:
> Another approach that I like better could be that all perl function
> and module names are always (automatically) prefixed by something like
> "ZopeExt::" in order to limit what can be done. Perl External Method
> modules would then need to go into the ./Extensions/ZopeExt directory
> (or anywhere else perl looks for modules).
It would seem to me that narrowing the use path this way is a good
thing.
We want to make sure that only modules that reside in
$ZOPEHOME/Extensions are searched for and imported.
I suppose some fiddling with the @INC array would do this. We'd need to
then unfiddle it when the method
was actually run. I see you have something like that in there commented
out.
> -----lib/python/Products/PerlExternalMethod__init__.py-------------->8---
> # Copyright 2000 Digital Creations
> # Copyright 2000 ActiveState Tool Corp.
> #
> # This module can be redistributed and/or modified
> # under the terms of the Zope Public Licence v1.0.
> #
> # This product includes software developed by Digital Creations
> # for use in the Z Object Publishing Environment (http://www.zope.org/).
>
> from Globals import Persistent, HTMLFile, MessageDialog
> import OFS.SimpleItem
> import AccessControl.Role
> import Acquisition
>
> from string import split, strip, join, find
>
> def get_perl_func(name, module):
> import perl
> if module:
> # XXX unshift(@INC, qw(./Extensions/perl ./Extensions)
> perl.require(module) # XXX do we need some kind of untaint here??
> f = perl.get_ref(name)
> return f
>
> # A class emulating internal func-code objects enough to fool
> # ZPublisher's mapply. Need to emulate co_varnames and co_argcount.
> # For Python External methods you find a similar class in
> # App.Extentions.
>
> class FuncCode:
> def __init__(self, args = ""):
> self.co_varnames = map(strip, split(args, ","))
> self.co_argcount = len(self.co_varnames)
>
> def args(self):
> return join(self.co_varnames, ", ")
>
> # This is the actual class that we will store instances of, in the
> # ZODB as this product is instantiated through manage_addPerlExtMethod
> # below. It stores enough information to obtain a reference to a single
> # perl function loaded from the file system on demand and the information
> # needed to fool mapply into thinking that this object is a function
> # by itself.
>
> class PerlExtMethod(OFS.SimpleItem.Item, Persistent, Acquisition.Explicit,
> AccessControl.Role.RoleManager):
> """Web-callable functions that encapsulate external perl functions."""
>
> # Emulated attributes of functions. The func_code class attribute
> # is not really used as instances override it with their own version.
> func_defaults=()
> func_code=FuncCode()
>
> # Set up various stuff that the Zope frameworks wants
> meta_type='Perl External Method'
> manage_options=(
> (
> {'label':'Properties', 'action':'manage_main',},
> {'label':'Try It', 'action':''},
> )
> +OFS.SimpleItem.Item.manage_options
> +AccessControl.Role.RoleManager.manage_options
> )
>
> __ac_permissions__=(
> ('View management screens', ('manage_main',)),
> ('Change External Methods', ('manage_edit',)),
> ('View', ('__call__','')),
> )
>
> # I am not really sure why :-(
> ZopeTime=Acquisition.Acquired
> HelpSys=Acquisition.Acquired
>
> def __init__(self, id, title, module, function, args):
> self.id=id
> self.manage_edit(title, module, function, args)
>
> manage_main=HTMLFile('methodEdit', globals())
>
> def manage_edit(self, title, module, function, args, REQUEST=None):
> """Change the perl external method"""
>
> self.title = str(title)
>
> module = strip(str(module))
> if module[-3:]=='.pm': module=module[:-3]
> self.module = module
>
> # XXX In order to improve security we might here require
> # that the function name is prefixed with some specific
> # package name (like "ZopeExt::"). This really allows
> # access to any function to be set up.
> function = strip(str(function))
> if find(function, "::") < 0:
> function = module + "::" + function
> self.function = function
>
> self.func_code = FuncCode(str(args))
>
> #self.getFunction(1,1)
> if REQUEST: return MessageDialog(
> title ='Changed %s' % self.id,
> message='%s has been updated' % self.id,
> action =REQUEST['URL2']+'/manage_main',
> target ='manage_main')
>
> def __call__(self, *args, **kw):
> """Invoke a PerlExternalMethod"""
>
> # The "_v_" prefix tells ZODB not try to store this thing
> if not hasattr(self, "_v_f"):
> self._v_f = get_perl_func(self.function, self.module)
> return apply(self._v_f, args, kw)
>
> def args(self):
> return self.func_code.args()
>
> manage_addPerlExtMethodForm=HTMLFile('methodAdd', globals())
>
> def manage_addPerlExtMethod(self, id, title, module, function, args,
> REQUEST=None):
> """Add a perl external method to a folder"""
> self._setObject(id, PerlExtMethod(id, title, module, function, args))
> if REQUEST:
> return self.manage_main(self, REQUEST)
>
> def initialize(context):
> context.registerClass(
> PerlExtMethod,
> constructors=(manage_addPerlExtMethodForm,
> manage_addPerlExtMethod),
> icon='extmethod.gif',
> )
>
> _______________________________________________
> Zope-perl maillist - Zope-perl@zope.org
> http://lists.zope.org/mailman/listinfo/zope-perl