source: documentViewer/documentViewer.py @ 33:b3fe3a50f605

Last change on this file since 33:b3fe3a50f605 was 32:b25c89d693cf, checked in by casties, 18 years ago

version 0.2.3 - first version with access control!

  • defaults to open when no access info
  • uses any logged in user for local access
File size: 17.1 KB
Line 
1from OFS.Folder import Folder
2from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
3from Products.PageTemplates.PageTemplateFile import PageTemplateFile
4from AccessControl import ClassSecurityInfo
5from AccessControl import getSecurityManager
6from Globals import package_home
7
8from Ft.Xml.Domlette import NonvalidatingReader
9from Ft.Xml.Domlette import PrettyPrint, Print
10from Ft.Xml import EMPTY_NAMESPACE
11
12import Ft.Xml.XPath
13
14import os.path
15import sys
16import cgi
17import urllib
18import zLOG
19
20def getInt(number, default=0):
21    """returns always an int (0 in case of problems)"""
22    try:
23        return int(number)
24    except:
25        return default
26   
27
28def getTextFromNode(nodename):
29    if nodename is None:
30        return ""
31    nodelist=nodename.childNodes
32    rc = ""
33    for node in nodelist:
34        if node.nodeType == node.TEXT_NODE:
35           rc = rc + node.data
36    return rc
37
38import socket
39
40def urlopen(url,timeout=2):
41        """urlopen mit timeout"""
42        socket.setdefaulttimeout(timeout)
43        ret=urllib.urlopen(url)
44        socket.setdefaulttimeout(5)
45        return ret
46
47
48##
49## documentViewer class
50##
51class documentViewer(Folder):
52    """document viewer"""
53
54    meta_type="Document viewer"
55   
56    security=ClassSecurityInfo()
57    manage_options=Folder.manage_options+(
58        {'label':'main config','action':'changeDocumentViewerForm'},
59        )
60
61    # templates and forms
62    viewer_main = PageTemplateFile('zpt/viewer_main', globals())
63    thumbs_main = PageTemplateFile('zpt/thumbs_main', globals())
64    image_main = PageTemplateFile('zpt/image_main', globals())
65    head_main = PageTemplateFile('zpt/head_main', globals())
66    docuviewer_css = PageTemplateFile('css/docuviewer.css', globals())
67
68    security.declareProtected('View management screens','changeDocumentViewerForm')   
69    changeDocumentViewerForm = PageTemplateFile('zpt/changeDocumentViewer', globals())
70
71   
72    def __init__(self,id,imageViewerUrl,title="",digilibBaseUrl=None,thumbcols=2,thumbrows=10,authgroups="mpiwg"):
73        """init document viewer"""
74        self.id=id
75        self.title=title
76        self.imageViewerUrl=imageViewerUrl
77        if not digilibBaseUrl:
78            self.digilibBaseUrl = self.findDigilibUrl()
79        else:
80            self.digilibBaseUrl = digilibBaseUrl
81        self.thumbcols = thumbcols
82        self.thumbrows = thumbrows
83        # authgroups is list of authorized groups (delimited by ,)
84        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
85        # add template folder so we can always use template.something
86        self.manage_addFolder('template')
87
88
89    security.declareProtected('View','index_html')
90    def index_html(self,mode,url,start=None,pn=1):
91        '''
92        view it
93        @param mode: defines which type of document is behind url
94        @param url: url which contains display information
95        '''
96       
97        zLOG.LOG("documentViewer (index)", zLOG.INFO, "mode: %s url:%s start:%s pn:%s"%(mode,url,start,pn))
98       
99        if not hasattr(self, 'template'):
100            # create template folder if it doesn't exist
101            self.manage_addFolder('template')
102           
103        if not self.digilibBaseUrl:
104            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
105           
106        docinfo = self.getDocinfo(mode=mode,url=url)
107        pageinfo = self.getPageinfo(start=start,current=pn,docinfo=docinfo)
108        pt = getattr(self.template, 'viewer_main')
109        return pt(docinfo=docinfo,pageinfo=pageinfo)
110 
111 
112    def getLink(self,param=None,val=None):
113        """link to documentviewer with parameter param set to val"""
114        params=cgi.parse_qs(self.REQUEST['QUERY_STRING'])
115        if param is not None:
116            if val is None:
117                if params.has_key(param):
118                    del params[param]
119            else:
120                params[param] = [str(val)]
121               
122        ps = "&".join(["%s=%s"%(k,urllib.quote(v[0])) for (k, v) in params.items()])
123        url=self.REQUEST['URL']+"?"+ps
124        #url=self.REQUEST['URL']+"?"+urllib.urlencode(params, doseq=True)
125        return url
126
127   
128    def getStyle(self, idx, selected, style=""):
129        """returns a string with the given style and append 'sel' if path == selected."""
130        #zLOG.LOG("documentViewer (getstyle)", zLOG.INFO, "idx: %s selected: %s style: %s"%(idx,selected,style))
131        if idx == selected:
132            return style + 'sel'
133        else:
134            return style   
135       
136    def accessOK(self, docinfo):
137        """returns if access to the resource is granted"""
138        access = docinfo.get('accessType', None)
139        if access is None:
140            # no information - no access (not yet)
141            return True
142        elif access == 'free':
143            return True
144       
145        print "access: ", access, " authgroups: ", self.authgroups
146        if access in self.authgroups:
147            # local access OK
148            user = getSecurityManager().getUser().getUserName()
149            print "user: ", user
150            return (user != "Anonymous User")
151       
152        zLOG.LOG("documentViewer (accessOK)", zLOG.INFO, "unknown access group %s"%access)
153        return False
154               
155       
156    def getDirinfoFromDigilib(self,path,docinfo=None):
157        """gibt param von dlInfo aus"""
158        if docinfo is None:
159            docinfo = {}
160           
161        imageUrl=self.digilibBaseUrl+"/dirInfo-xml.jsp?mo=dir&fn="+path
162   
163        zLOG.LOG("documentViewer (getparamfromdigilib)", zLOG.INFO, "dirInfo from %s"%(imageUrl))
164       
165        try:
166            dom = NonvalidatingReader.parseUri(imageUrl)
167        except:
168            zLOG.LOG("documentViewer (getparamfromdigilib)", zLOG.ERROR, "error reading %s"%(imageUrl))
169            raise IOError("Unable to get dirinfo from %s"%(imageUrl))
170       
171        params=dom.xpath("//dir/size")
172        zLOG.LOG("documentViewer (getparamfromdigilib)", zLOG.INFO, "dirInfo:size"%params)
173       
174        if params:
175            docinfo['numPages'] = int(getTextFromNode(params[0]))
176        else:
177            docinfo['numPages'] = 0
178                       
179        return docinfo
180   
181           
182    def getAuthinfoFromIndexMeta(self,path,docinfo=None,dom=None):
183        """gets authorization info from the index.meta file at url or given by dom"""
184        zLOG.LOG("documentViewer (getbibinfofromindexmeta)", zLOG.INFO,"path: %s"%(path))
185       
186        access = None
187       
188        if docinfo is None:
189            docinfo = {}
190           
191        if dom is None:
192            server=self.digilibBaseUrl+"/servlet/Texter?fn="
193            path="/".join(path.split("/")[0:-1])
194            metaUrl=server+path+"/index.meta"
195            try:
196                dom = NonvalidatingReader.parseUri(metaUrl)
197            except:
198                return docinfo
199           
200        acctype = dom.xpath("//access-conditions/access/@type")
201        if acctype and (len(acctype)>0):
202            access=acctype[0].value
203            if access == 'group':
204                access = getTextFromNode(dom.xpath("//access-conditions/access/name")[0]).lower()
205           
206        docinfo['accessType'] = access
207        return docinfo
208   
209       
210    def getBibinfoFromIndexMeta(self,path,docinfo=None,dom=None):
211        """gets bibliographical info from the index.meta file at url or given by dom"""
212        zLOG.LOG("documentViewer (getbibinfofromindexmeta)", zLOG.INFO,"path: %s"%(path))
213       
214        if docinfo is None:
215            docinfo = {}
216           
217        if dom is None:
218            server=self.digilibBaseUrl+"/servlet/Texter?fn="
219            path="/".join(path.split("/")[0:-1])
220            metaUrl=server+path+"/index.meta"
221            try:
222                dom = NonvalidatingReader.parseUri(metaUrl)
223            except:
224                return docinfo
225       
226        metaData=self.metadata.main.meta.bib
227        bibtype=dom.xpath("//bib/@type")
228        if bibtype and (len(bibtype)>0):
229            bibtype=bibtype[0].value
230        else:
231            bibtype="generic"
232        bibtype=bibtype.replace("-"," ") # wrong typesiin index meta "-" instead of " " (not wrong! ROC)
233        bibmap=metaData.generateMappingForType(bibtype)
234        print "bibmap: ", bibmap, " for: ", bibtype
235        # if there is no mapping bibmap is empty (mapping sometimes has empty fields)
236        if len(bibmap) > 0 and len(bibmap['author'][0]) > 0:
237            docinfo['author']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['author'][0])[0])
238            docinfo['title']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['title'][0])[0])
239            docinfo['year']=getTextFromNode(dom.xpath("//bib/%s"%bibmap['year'][0])[0])
240       
241        return docinfo
242
243       
244    def getDocinfoFromTextTool(self,url,dom=None,docinfo=None):
245       """parse texttool tag in index meta"""
246       zLOG.LOG("documentViewer (getdocinfofromtexttool)", zLOG.INFO,"url: %s"%(url))
247       if docinfo is None:
248           docinfo = {}
249           
250       if dom is None:
251           try:
252               dom = NonvalidatingReader.parseUri(url)
253           except:
254               zLOG.LOG("documentViewer (parseUrlTexttool)", zLOG.INFO,"%s (%s)"%sys.exc_info()[0:2])
255               raise IOError("Unable to get texttool info from %s"%(url))
256       
257       archiveNames=dom.xpath("//resource/name")
258       if archiveNames and (len(archiveNames)>0):
259           archiveName=getTextFromNode(archiveNames[0])
260       
261       archivePaths=dom.xpath("//resource/archive-path")
262       if archivePaths and (len(archivePaths)>0):
263           archivePath=getTextFromNode(archivePaths[0])
264           # clean up archive path
265           if archivePath[0] != '/':
266               archivePath = '/' + archivePath
267           if not archivePath.endswith(archiveName):
268               archivePath += "/" + archiveName
269       else:
270           archivePath=None
271       
272       images=dom.xpath("//texttool/image")
273       if images and (len(images)>0):
274           image=getTextFromNode(images[0])
275       else:
276           image=None
277           
278       if image and archivePath:
279           print "image: ", image, " archivepath: ", archivePath
280           image=os.path.join(archivePath,image)
281           image=image.replace("/mpiwg/online",'')
282           docinfo=self.getDirinfoFromDigilib(image,docinfo=docinfo)
283           docinfo['imagePath'] = image
284           docinfo['imageURL'] = self.digilibBaseUrl+"/servlet/Scaler?fn="+image
285           
286       viewerUrls=dom.xpath("//texttool/digiliburlprefix")
287       if viewerUrls and (len(viewerUrls)>0):
288           viewerUrl=getTextFromNode(viewerUrls[0])
289           docinfo['viewerURL'] = viewerUrl
290                 
291       textUrls=dom.xpath("//texttool/text")
292       if textUrls and (len(textUrls)>0):
293           textUrl=getTextFromNode(textUrls[0])
294           docinfo['textURL'] = textUrl
295                     
296       docinfo = self.getBibinfoFromIndexMeta(url,docinfo=docinfo,dom=dom)
297       docinfo = self.getAuthinfoFromIndexMeta(url,docinfo=docinfo,dom=dom)
298       return docinfo
299   
300
301    def getDocinfoFromImagePath(self,path,docinfo=None):
302        """path ist the path to the images it assumes that the index.meta file is one level higher."""
303        zLOG.LOG("documentViewer (getdocinfofromimagepath)", zLOG.INFO,"path: %s"%(path))
304        if docinfo is None:
305            docinfo = {}
306        path=path.replace("/mpiwg/online","")
307        docinfo['imagePath'] = path
308        docinfo=self.getDirinfoFromDigilib(path,docinfo=docinfo)
309        imageUrl=self.digilibBaseUrl+"/servlet/Scaler?fn="+path
310        docinfo['imageURL'] = imageUrl
311       
312        docinfo = self.getBibinfoFromIndexMeta(path,docinfo=docinfo)
313        docinfo = self.getAuthinfoFromIndexMeta(path,docinfo=docinfo)
314        return docinfo
315   
316   
317    def getDocinfo(self, mode, url):
318        """returns docinfo depending on mode"""
319        zLOG.LOG("documentViewer (getdocinfo)", zLOG.INFO,"mode: %s, url: %s"%(mode,url))
320        # look for cached docinfo in session
321        if self.REQUEST.SESSION.has_key('docinfo'):
322            docinfo = self.REQUEST.SESSION['docinfo']
323            # check if its still current
324            if docinfo is not None and docinfo.get('mode') == mode and docinfo.get('url') == url:
325                zLOG.LOG("documentViewer (getdocinfo)", zLOG.INFO,"docinfo in session: %s"%docinfo)
326                return docinfo
327        # new docinfo
328        docinfo = {'mode': mode, 'url': url}
329        if mode=="texttool": #index.meta with texttool information
330            docinfo = self.getDocinfoFromTextTool(url, docinfo=docinfo)
331        elif mode=="imagepath":
332            docinfo = self.getDocinfoFromImagePath(url, docinfo=docinfo)
333        else:
334            zLOG.LOG("documentViewer (getdocinfo)", zLOG.ERROR,"unknown mode!")
335        zLOG.LOG("documentViewer (getdocinfo)", zLOG.INFO,"docinfo: %s"%docinfo)
336        self.REQUEST.SESSION['docinfo'] = docinfo
337        return docinfo
338       
339       
340    def getPageinfo(self, current, start=None, rows=None, cols=None, docinfo=None):
341        """returns pageinfo with the given parameters"""
342        pageinfo = {}
343        current = getInt(current)
344        pageinfo['current'] = current
345        rows = int(rows or self.thumbrows)
346        pageinfo['rows'] = rows
347        cols = int(cols or self.thumbcols)
348        pageinfo['cols'] = cols
349        grpsize = cols * rows
350        pageinfo['groupsize'] = grpsize
351        start = getInt(start, default=(int(current / grpsize) * grpsize +1))
352        pageinfo['start'] = start
353        pageinfo['end'] = start + grpsize
354        if docinfo is not None:
355            np = int(docinfo['numPages'])
356            pageinfo['end'] = min(pageinfo['end'], np)
357            pageinfo['numgroups'] = int(np / grpsize)
358            if np % grpsize > 0:
359                pageinfo['numgroups'] += 1
360               
361        return pageinfo
362               
363    def text(self,mode,url,pn):
364        """give text"""
365        if mode=="texttool": #index.meta with texttool information
366            (viewerUrl,imagepath,textpath)=parseUrlTextTool(url)
367       
368        print textpath
369        try:
370            dom = NonvalidatingReader.parseUri(textpath)
371        except:
372            return None
373   
374        list=[]
375        nodes=dom.xpath("//pb")
376
377        node=nodes[int(pn)-1]
378       
379        p=node
380       
381        while p.tagName!="p":
382            p=p.parentNode
383       
384       
385        endNode=nodes[int(pn)]
386       
387       
388        e=endNode
389       
390        while e.tagName!="p":
391            e=e.parentNode
392       
393       
394        next=node.parentNode
395       
396        #sammle s
397        while next and (next!=endNode.parentNode):
398            list.append(next)   
399            next=next.nextSibling   
400        list.append(endNode.parentNode)
401       
402        if p==e:# beide im selben paragraphen
403            pass
404#    else:
405#            next=p
406#            while next!=e:
407#                print next,e
408#                list.append(next)
409#                next=next.nextSibling
410#           
411#        for x in list:
412#            PrettyPrint(x)
413#
414#        return list
415#
416
417    def findDigilibUrl(self):
418        """try to get the digilib URL from zogilib"""
419        url = self.imageViewerUrl[:-1] + "/getScalerUrl"
420        try:
421            scaler = urlopen(url).read()
422            return scaler.replace("/servlet/Scaler?", "")
423        except:
424            return None
425   
426    def changeDocumentViewer(self,imageViewerUrl,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=10,authgroups='mpiwg',RESPONSE=None):
427        """init document viewer"""
428        self.title=title
429        self.imageViewerUrl=imageViewerUrl
430        self.digilibBaseUrl = digilibBaseUrl
431        self.thumbrows = thumbrows
432        self.thumbcols = thumbcols
433        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
434        if RESPONSE is not None:
435            RESPONSE.redirect('manage_main')
436   
437   
438       
439       
440#    security.declareProtected('View management screens','renameImageForm')
441
442def manage_AddDocumentViewerForm(self):
443    """add the viewer form"""
444    pt=PageTemplateFile('zpt/addDocumentViewer', globals()).__of__(self)
445    return pt()
446 
447def manage_AddDocumentViewer(self,id,imageViewerUrl="",title="",RESPONSE=None):
448    """add the viewer"""
449    newObj=documentViewer(id,imageViewerUrl,title)
450    self._setObject(id,newObj)
451   
452    if RESPONSE is not None:
453        RESPONSE.redirect('manage_main')
454
455
456##
457## DocumentViewerTemplate class
458##
459class DocumentViewerTemplate(ZopePageTemplate):
460    """Template for document viewer"""
461    meta_type="DocumentViewer Template"
462
463
464def manage_addDocumentViewerTemplateForm(self):
465    """Form for adding"""
466    pt=PageTemplateFile('zpt/addDocumentViewerTemplate', globals()).__of__(self)
467    return pt()
468
469def manage_addDocumentViewerTemplate(self, id='viewer_main', title=None, text=None,
470                           REQUEST=None, submit=None):
471    "Add a Page Template with optional file content."
472
473    self._setObject(id, DocumentViewerTemplate(id))
474    ob = getattr(self, id)
475    ob.pt_edit(open(os.path.join(package_home(globals()),'zpt/viewer_main.zpt')).read(),None)
476    if title:
477        ob.pt_setTitle(title)
478    try:
479        u = self.DestinationURL()
480    except AttributeError:
481        u = REQUEST['URL1']
482       
483    u = "%s/%s" % (u, urllib.quote(id))
484    REQUEST.RESPONSE.redirect(u+'/manage_main')
485    return ''
486
487
488   
Note: See TracBrowser for help on using the repository browser.