source: documentViewer/documentViewer.py @ 41:0c8ee8fcfd76

Last change on this file since 41:0c8ee8fcfd76 was 41:0c8ee8fcfd76, checked in by casties, 18 years ago

some more logging

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