File: ReplaceSupport.py

package info (click to toggle)
zope-replacesupport 1.0.2-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 168 kB
  • ctags: 155
  • sloc: python: 743; makefile: 38; sh: 25
file content (355 lines) | stat: -rw-r--r-- 12,011 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# ReplaceSupport 1.0.2
# (c) 2000-2004, Stefan H. Holek, stefan@epy.co.at
# http://zope.org/Members/shh/ReplaceSupport
# License: ZPL
# Zope: 2.3-2.7

__doc__ = 'Replace Support'
__version__ = '1.0.2'

import sys, os, string, time, Globals, ExtensionClass
from DocumentTemplate.DT_Util import Eval
from AccessControl.Permission import name_trans
from AccessControl import getSecurityManager
from Globals import HTMLFile
from DocumentTemplate.DT_Util import InstanceDict, TemplateDict
from DateTime import DateTime
from string import find, replace

# 2.4 compatibility hack
try: 
    from DocumentTemplate.DT_Util import expr_globals
except ImportError: 
    expr_globals=None

# 2.4 compatibility hack
try: 
    from AccessControl.DTML import RestrictedDTML
    class td(RestrictedDTML, TemplateDict):
        pass
except ImportError: 
    from AccessControl import getSecurityManager
    class td(TemplateDict):
        def validate(self, inst, parent, name, value, md):
            return getSecurityManager().validate(inst, parent, name, value)


class ReplaceSupport(ExtensionClass.Base):
    """Replace support for Zope Folders"""

    manage_replaceForm=HTMLFile('dtml/replaceForm', globals(), management_view='Replace', 
                                 help_product='ReplaceSupport', help_topic='Replace.stx')
    manage_replaceResult=HTMLFile('dtml/replaceResult', globals(), management_view='Replace',
                                   help_product='ReplaceSupport', help_topic='Replace.stx')

    __ac_permissions__=(
        ('View management screens',
         ('manage_replaceForm', 
          'manage_replaceResult',
          'getReplaceHandlerMetaTypes',)),
        ('Search & replace in objects',
         ('manage_replaceForm', 
          'manage_replaceResult', 
          'getReplaceHandlerMetaTypes',
          'ZopeReplace', 'PrincipiaReplace',)),
        )

    manage_options=(
        {'label':'Replace', 'action':'manage_replaceForm',
         'help':('ReplaceSupport','Replace.stx')},   
        ) 


    def getReplaceHandlerMetaTypes(self):
        """Return list of handler meta types"""
        return self._ReplaceHandlerRegistry.getHandlerMetaTypes()
   

    def ZopeReplace(self, obj, obj_ids=None, obj_metatypes=None,
                    obj_searchterm=None, obj_replaceterm=None, obj_expr=None,
                    obj_mtime=None, obj_mspec=None,
                    obj_permission=None, obj_roles=None,
                    search_sub=0,
                    REQUEST=None, result=None, pre=''):
        """Zope Replace interface"""
        return self._ZopeReplace(obj, obj_ids, obj_metatypes,
                                 obj_searchterm, obj_replaceterm, obj_expr,
                                 obj_mtime, obj_mspec,
                                 obj_permission, obj_roles,
                                 search_sub,
                                 REQUEST, result, pre,
                                 check_change_permission=1)

    PrincipiaReplace = ZopeReplace


    def _ZopeReplace(self, obj, obj_ids=None, obj_metatypes=None,
                     obj_searchterm=None, obj_replaceterm=None, obj_expr=None,
                     obj_mtime=None, obj_mspec=None,
                     obj_permission=None, obj_roles=None,
                     search_sub=0,
                     REQUEST=None, result=None, pre='',
                     check_change_permission=0):
        """Zope Replace interface; unrestricted"""
	
        if result is None:
            result=[]

            if obj_metatypes and 'all' in obj_metatypes:
                obj_metatypes=None
                
            if obj_mtime and type(obj_mtime)==type('s'):
                obj_mtime=DateTime(obj_mtime).timeTime()

            if obj_permission:
                obj_permission=p_name(obj_permission)

            if obj_roles and type(obj_roles) is type('s'):
                obj_roles=[obj_roles]
                
            if obj_expr:
                # Setup expr machinations
                md=td()
                if hasattr(REQUEST, 'AUTHENTICATED_USER'):
                    md.AUTHENTICATED_USER=REQUEST.AUTHENTICATED_USER
                obj_expr=(Eval(obj_expr, expr_globals), md, md._push, md._pop)

        base=obj
        if hasattr(obj, 'aq_base'):
            base=obj.aq_base

        if hasattr(base, 'objectItems'):
	    try:    items=obj.objectItems()
	    except: return result
        else:
	    if getattr(base, 'meta_type', None) == 'Z Class':
	        try:    items=obj.propertysheets.methods.objectItems()
		except: return result
	    else:
		return result

        try: add_result=result.append
        except:
            raise AttributeError, `result`

        for id, ob in items:
            if pre: p="%s/%s" % (pre, id)
            else:   p=id
            
            dflag=0
            if hasattr(ob, '_p_changed') and (ob._p_changed == None):
                dflag=1

            if hasattr(ob, 'aq_base'):
                bs=ob.aq_base
            else: bs=ob

            if (
                (not obj_ids or absattr(bs.getId()) in obj_ids)
                and
                (not obj_metatypes or (hasattr(bs, 'meta_type') and
                 bs.meta_type in obj_metatypes))
                and
                (not obj_searchterm or
                 (hasattr(ob, 'PrincipiaSearchSource') and
                  find(ob.PrincipiaSearchSource(), obj_searchterm) >= 0
                  ))
                and
                (not obj_expr or expr_match(ob, obj_expr))
                and
                (not obj_mtime or mtime_match(ob, obj_mtime, obj_mspec))
                and
                ( (not obj_permission or not obj_roles) or \
                   role_match(ob, obj_permission, obj_roles)
                )
                ):
		# Find and apply a handler for this object
		handler = self._ReplaceHandlerRegistry.getHandler(ob.meta_type)
		if handler and (not check_change_permission or \
                    getSecurityManager().checkPermission(handler.getChangePermission(), ob)):
                    body = replace(handler.getBody(ob), obj_searchterm, obj_replaceterm)
                    params = replace(handler.getParams(ob), obj_searchterm, obj_replaceterm)	
                    handler.manageEdit(ob, body, params)
                    add_result((p, ob))
                    dflag = 0

            is_zclass = getattr(bs, 'meta_type', None) == 'Z Class'
            if search_sub and (hasattr(bs, 'objectItems') or is_zclass):
	        if is_zclass:
		    subob = ob.propertysheets.methods
		    sub_p = '%s/propertysheets/methods' % p
		else:
		    subob = ob
		    sub_p = p
		self._ZopeReplace(subob, obj_ids, obj_metatypes,
                                  obj_searchterm, obj_replaceterm, obj_expr,
                                  obj_mtime, obj_mspec,
                                  obj_permission, obj_roles,
                                  search_sub,
                                  REQUEST, result, sub_p,
                                  check_change_permission)

            if dflag: ob._p_deactivate()

        return result

    _PrincipiaReplace = _ZopeReplace
 

    # Unused and unlikely to change 'cause I do not seem to figure out
    # what to do with it...
if 0:
    def ZopeReplaceAndApply(self, obj, obj_ids=None, obj_metatypes=None,
                         obj_searchterm=None, obj_replaceterm=None, obj_expr=None,
                         obj_mtime=None, obj_mspec=None,
                         obj_permission=None, obj_roles=None,
                         search_sub=0,
                         REQUEST=None, result=None, pre='',
                         apply_func=None, apply_path=''):
        """Zope Replace interface and apply"""

        if result is None:
            result=[]

            if obj_metatypes and 'all' in obj_metatypes:
                obj_metatypes=None
                
            if obj_mtime and type(obj_mtime)==type('s'):
                obj_mtime=DateTime(obj_mtime).timeTime()

            if obj_permission:
                obj_permission=p_name(obj_permission)

            if obj_roles and type(obj_roles) is type('s'):
                obj_roles=[obj_roles]
                
            if obj_expr:
                # Setup expr machinations
                md=td()
                if hasattr(REQUEST, 'AUTHENTICATED_USER'):
                    md.AUTHENTICATED_USER=REQUEST.AUTHENTICATED_USER
                obj_expr=(Eval(obj_expr, expr_globals), md, md._push, md._pop)

        base=obj
        if hasattr(obj, 'aq_base'):
            base=obj.aq_base

        if not hasattr(base, 'objectItems'):
            return result
        try:    items=base.objectItems()
        except: return result

        try: add_result=result.append
        except:
            raise AttributeError, `result`

        for id, ob in items:
            if pre: p="%s/%s" % (pre, id)
            else:   p=id
            
            dflag=0
            if hasattr(ob, '_p_changed') and (ob._p_changed == None):
                dflag=1

            if hasattr(ob, 'aq_base'):
                bs=ob.aq_base
            else: bs=ob

            if (
                (not obj_ids or absattr(bs.getId()) in obj_ids)
                and
                (not obj_metatypes or (hasattr(bs, 'meta_type') and
                 bs.meta_type in obj_metatypes))
                and
                (not obj_searchterm or
                 (hasattr(ob, 'PrincipiaSearchSource') and
                  find(ob.PrincipiaSearchSource(), obj_searchterm) >= 0
                  ))
                and
                (not obj_expr or expr_match(ob, obj_expr))
                and
                (not obj_mtime or mtime_match(ob, obj_mtime, obj_mspec))
                and
                ( (not obj_permission or not obj_roles) or \
                   role_match(ob, obj_permission, obj_roles)
                )
                ):
                if apply_func:
                    apply_func(ob, (apply_path+'/'+p))
                else:
                    add_result((p, ob))
                    dflag=0
                    
            if search_sub and hasattr(bs, 'objectItems'):
                self.ZopeReplaceAndApply(ob, obj_ids, obj_metatypes,
                                      obj_searchterm, obj_replaceterm, obj_expr,
                                      obj_mtime, obj_mspec,
                                      obj_permission, obj_roles,
                                      search_sub,
                                      REQUEST, result, p,
                                      apply_func, apply_path)
            if dflag: ob._p_deactivate()

        return result



def expr_match(ob, ed, c=InstanceDict, r=0):
    e, md, push, pop=ed
    push(c(ob, md))
    try: r=e.eval(md)
    finally:
        pop()
        return r


def mtime_match(ob, t, q, fn=hasattr):
    if not fn(ob, '_p_mtime'):
        return 0    
    return q=='<' and (ob._p_mtime < t) or (ob._p_mtime > t)


def role_match(ob, permission, roles, lt=type([]), tt=type(())):
    pr=[]
    fn=pr.append
    
    while 1:
        if hasattr(ob, permission):
            p=getattr(ob, permission)
            if type(p) is lt:
                map(fn, p)
                if hasattr(ob, 'aq_parent'):
                    ob=ob.aq_parent
                    continue
                break
            if type(p) is tt:
                map(fn, p)
                break
            if p is None:
                map(fn, ('Manager', 'Anonymous'))
                break

        if hasattr(ob, 'aq_parent'):
            ob=ob.aq_parent
            continue
        break

    for role in roles:
        if not (role in pr):
            return 0
    return 1


Globals.default__class_init__(ReplaceSupport)

# Helper functions

def absattr(attr):
    if callable(attr): return attr()
    return attr


def p_name(name):
    return '_' + string.translate(name, name_trans) + '_Permission'