source: documentViewer/documentViewer.py @ 507:3c01e8f4e72b

elementtree
Last change on this file since 507:3c01e8f4e72b was 507:3c01e8f4e72b, checked in by casties, 12 years ago

renamed config tab in ZMI

File size: 33.0 KB
Line 
1from OFS.Folder import Folder
2from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
3from Products.PageTemplates.PageTemplateFile import PageTemplateFile
4from App.ImageFile import ImageFile
5from AccessControl import ClassSecurityInfo
6from AccessControl import getSecurityManager
7from Globals import package_home
8
9import xml.etree.ElementTree as ET
10
11import os
12import sys
13import urllib
14import logging
15import math
16import urlparse 
17import re
18import string
19
20from SrvTxtUtils import getInt, getText, getHttpData, refreshingImageFileIndexHtml
21   
22def serializeNode(node, encoding="utf-8"):
23    """returns a string containing node as XML"""
24    s = ET.tostring(node)
25   
26    # 4Suite:
27    #    stream = cStringIO.StringIO()
28    #    Ft.Xml.Domlette.Print(node, stream=stream, encoding=encoding)
29    #    s = stream.getvalue()
30    #    stream.close()
31    return s
32
33def browserCheck(self):
34    """check the browsers request to find out the browser type"""
35    bt = {}
36    ua = self.REQUEST.get_header("HTTP_USER_AGENT")
37    bt['ua'] = ua
38    bt['isIE'] = False
39    bt['isN4'] = False
40    bt['versFirefox']=""
41    bt['versIE']=""
42    bt['versSafariChrome']=""
43    bt['versOpera']=""
44   
45    if string.find(ua, 'MSIE') > -1:
46        bt['isIE'] = True
47    else:
48        bt['isN4'] = (string.find(ua, 'Mozilla/4.') > -1)
49    # Safari oder Chrome identification   
50    try:
51        nav = ua[string.find(ua, '('):]
52        nav1=ua[string.find(ua,')'):]
53        nav2=nav1[string.find(nav1,'('):]
54        nav3=nav2[string.find(nav2,')'):]
55        ie = string.split(nav, "; ")[1]
56        ie1 =string.split(nav1, " ")[2]
57        ie2 =string.split(nav3, " ")[1]
58        ie3 =string.split(nav3, " ")[2]
59        if string.find(ie3, "Safari") >-1:
60            bt['versSafariChrome']=string.split(ie2, "/")[1]
61    except: pass
62    # IE identification
63    try:
64        nav = ua[string.find(ua, '('):]
65        ie = string.split(nav, "; ")[1]
66        if string.find(ie, "MSIE") > -1:
67            bt['versIE'] = string.split(ie, " ")[1]
68    except:pass
69    # Firefox identification
70    try:
71        nav = ua[string.find(ua, '('):]
72        nav1=ua[string.find(ua,')'):]
73        if string.find(ie1, "Firefox") >-1:
74            nav5= string.split(ie1, "/")[1]
75            logging.debug("FIREFOX: %s"%(nav5))
76            bt['versFirefox']=nav5[0:3]                   
77    except:pass
78    #Opera identification
79    try:
80        if string.find(ua,"Opera") >-1:
81            nav = ua[string.find(ua, '('):]
82            nav1=nav[string.find(nav,')'):]
83            bt['versOpera']=string.split(nav1,"/")[2]
84    except:pass
85   
86    bt['isMac'] = string.find(ua, 'Macintosh') > -1
87    bt['isWin'] = string.find(ua, 'Windows') > -1
88    bt['isIEWin'] = bt['isIE'] and bt['isWin']
89    bt['isIEMac'] = bt['isIE'] and bt['isMac']
90    bt['staticHTML'] = False
91
92    return bt
93
94def getParentPath(path, cnt=1):
95    """returns pathname shortened by cnt"""
96    # make sure path doesn't end with /
97    path = path.rstrip('/')
98    # split by /, shorten, and reassemble
99    return '/'.join(path.split('/')[0:-cnt])
100
101##
102## documentViewer class
103##
104class documentViewer(Folder):
105    """document viewer"""
106    meta_type="Document viewer"
107   
108    security=ClassSecurityInfo()
109    manage_options=Folder.manage_options+(
110        {'label':'Configuration','action':'changeDocumentViewerForm'},
111        )
112   
113    metadataService = None
114    """MetaDataFolder instance"""
115
116    # templates and forms
117    viewer_text = PageTemplateFile('zpt/viewer_text', globals())
118    viewer_xml = PageTemplateFile('zpt/viewer_xml', globals())
119    viewer_images = PageTemplateFile('zpt/viewer_images', globals())
120    viewer_index = PageTemplateFile('zpt/viewer_index', globals())
121    toc_thumbs = PageTemplateFile('zpt/toc_thumbs', globals())
122    toc_text = PageTemplateFile('zpt/toc_text', globals())
123    toc_figures = PageTemplateFile('zpt/toc_figures', globals())
124    toc_none = PageTemplateFile('zpt/toc_none', globals())
125    common_template = PageTemplateFile('zpt/common_template', globals())
126    info_xml = PageTemplateFile('zpt/info_xml', globals())
127    docuviewer_css = ImageFile('css/docuviewer.css',globals())
128    # make ImageFile better for development
129    docuviewer_css.index_html = refreshingImageFileIndexHtml
130    jquery_js = ImageFile('js/jquery.js',globals())
131   
132   
133    def __init__(self,id,imageScalerUrl=None,textServerName=None,title="",digilibBaseUrl=None,thumbcols=2,thumbrows=5,authgroups="mpiwg"):
134        """init document viewer"""
135        self.id=id
136        self.title=title
137        self.thumbcols = thumbcols
138        self.thumbrows = thumbrows
139        # authgroups is list of authorized groups (delimited by ,)
140        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
141        # create template folder so we can always use template.something
142       
143        templateFolder = Folder('template')
144        self['template'] = templateFolder # Zope-2.12 style
145        #self._setObject('template',templateFolder) # old style
146        try:
147            import MpdlXmlTextServer
148            textServer = MpdlXmlTextServer.MpdlXmlTextServer(id='fulltextclient',serverName=textServerName)
149            templateFolder['fulltextclient'] = textServer
150            #templateFolder._setObject('fulltextclient',textServer)
151        except Exception, e:
152            logging.error("Unable to create MpdlXmlTextServer for fulltextclient: "+str(e))
153           
154        try:
155            from Products.zogiLib.zogiLib import zogiLib
156            zogilib = zogiLib(id="zogilib", title="zogilib for docuviewer", dlServerURL=imageScalerUrl, layout="book")
157            templateFolder['zogilib'] = zogilib
158            #templateFolder._setObject('zogilib',zogilib)
159        except Exception, e:
160            logging.error("Unable to create zogiLib for zogilib: "+str(e))
161           
162        try:
163            # assume MetaDataFolder instance is called metadata
164            self.metadataService = getattr(self, 'metadata')
165        except Exception, e:
166            logging.error("Unable to find MetaDataFolder 'metadata': "+str(e))
167           
168        if digilibBaseUrl is not None:
169            self.digilibBaseUrl = digilibBaseUrl
170           
171       
172    # proxy text server methods to fulltextclient
173    def getTextPage(self, **args):
174        """returns full text content of page"""
175        return self.template.fulltextclient.getTextPage(**args)
176
177    def getToc(self, **args):
178        """returns the full table of contents (in internal format)"""
179        return self.template.fulltextclient.getToc(**args)
180
181    def getTocPage(self, **args):
182        """returns one page of the table of contents"""
183        return self.template.fulltextclient.getTocPage(**args)
184
185    def getPlacesOnPage(self, **args):
186        """get list of gis places on one page"""
187        return self.template.fulltextclient.getPlacesOnPage(**args)
188 
189    #WTF?
190    thumbs_main_rss = PageTemplateFile('zpt/thumbs_main_rss', globals())
191    security.declareProtected('View','thumbs_rss')
192    def thumbs_rss(self,mode,url,viewMode="auto",start=None,pn=1):
193        '''
194        view it
195        @param mode: defines how to access the document behind url
196        @param url: url which contains display information
197        @param viewMode: if images display images, if text display text, default is images (text,images or auto)
198       
199        '''
200        logging.debug("HHHHHHHHHHHHHH:load the rss")
201        logging.debug("documentViewer (index) mode: %s url:%s start:%s pn:%s"%(mode,url,start,pn))
202       
203        if not hasattr(self, 'template'):
204            # create template folder if it doesn't exist
205            self.manage_addFolder('template')
206           
207        if not self.digilibBaseUrl:
208            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
209           
210        docinfo = self.getDocinfo(mode=mode,url=url)
211        #pageinfo = self.getPageinfo(start=start,current=pn,docinfo=docinfo)
212        pageinfo = self.getPageinfo(start=start,current=pn, docinfo=docinfo)
213        ''' ZDES '''
214        pt = getattr(self.template, 'thumbs_main_rss')
215       
216        if viewMode=="auto": # automodus gewaehlt
217            if docinfo.has_key("textURL") or docinfo.get('textURLPath',None): #texturl gesetzt und textViewer konfiguriert
218                viewMode="text"
219            else:
220                viewMode="images"
221               
222        return pt(docinfo=docinfo,pageinfo=pageinfo,viewMode=viewMode)
223
224 
225    security.declareProtected('View','index_html')
226    def index_html(self,url,mode="texttool",viewMode="auto",viewLayer=None,tocMode="thumbs",start=1,pn=1):
227        """
228        view page
229        @param url: url which contains display information
230        @param mode: defines how to access the document behind url
231        @param viewMode: 'images': display images, 'text': display text, 'xml': display xml, default is 'auto'
232        @param viewLayer: sub-type of viewMode, e.g. 'dict' for viewMode='text'
233        @param tocMode: type of 'table of contents' for navigation (thumbs, text, figures, none)
234        """
235       
236        logging.debug("documentViewer(index_html) mode=%s url=%s viewMode=%s viewLayer=%s start=%s pn=%s"%(mode,url,viewMode,viewLayer,start,pn))
237       
238        if not hasattr(self, 'template'):
239            # this won't work
240            logging.error("template folder missing!")
241            return "ERROR: template folder missing!"
242           
243        if not getattr(self, 'digilibBaseUrl', None):
244            self.digilibBaseUrl = self.findDigilibUrl() or "http://digilib.mpiwg-berlin.mpg.de/digitallibrary"
245           
246        docinfo = self.getDocinfo(mode=mode,url=url)
247       
248        if tocMode != "thumbs":
249            # get table of contents
250            docinfo = self.getToc(mode=tocMode, docinfo=docinfo)
251
252        # auto viewMode: text if there is a text else images
253        if viewMode=="auto": 
254            if docinfo.get('textURL', None) or docinfo.get('textURLPath', None): 
255                viewMode = "text"
256                viewLayer = "dict"
257            else:
258                viewMode = "images"
259               
260        elif viewMode == "text_dict":
261            # legacy fix
262            viewMode = "text"
263            viewLayer = "dict"
264           
265        # stringify viewLayer
266        if isinstance(viewLayer, list):
267            logging.debug("index_html: viewLayer is list:%s"%viewLayer)
268            viewLayer = ','.join([t for t in viewLayer if t])
269                       
270        pageinfo = self.getPageinfo(start=start, current=pn, docinfo=docinfo, viewMode=viewMode, viewLayer=viewLayer, tocMode=tocMode)
271                   
272        # get template /template/viewer_$viewMode
273        pt = getattr(self.template, 'viewer_%s'%viewMode, None)
274        if pt is None:
275            logging.error("No template for viewMode=%s!"%viewMode)
276            # TODO: error page?
277            return "No template for viewMode=%s!"%viewMode
278       
279        # and execute with parameters
280        return pt(docinfo=docinfo, pageinfo=pageinfo)
281 
282    #WTF?
283    def generateMarks(self,mk):
284        ret=""
285        if mk is None:
286            return ""
287        if not isinstance(mk, list):
288            mk=[mk]
289        for m in mk:
290            ret+="mk=%s"%m
291        return ret
292   
293   
294    def getBrowser(self):
295        """getBrowser the version of browser """
296        bt = browserCheck(self)
297        logging.debug("BROWSER VERSION: %s"%(bt))
298        return bt
299       
300    def findDigilibUrl(self):
301        """try to get the digilib URL from zogilib"""
302        url = self.template.zogilib.getDLBaseUrl()
303        return url
304   
305    def getScalerUrl(self, fn=None, pn=None, dw=100, dh=100, docinfo=None):
306        """returns URL to digilib Scaler with params"""
307        url = None
308        if docinfo is not None:
309            url = docinfo.get('imageURL', None)
310           
311        if url is None:
312            url = "%s/servlet/Scaler?"%self.digilibBaseUrl
313            if fn is None and docinfo is not None:
314                fn = docinfo.get('imagePath','')
315           
316            url += "fn=%s"%fn
317           
318        if pn:
319            url += "&pn=%s"%pn
320           
321        url += "&dw=%s&dh=%s"%(dw,dh)
322        return url
323
324    def getDocumentViewerURL(self):
325        """returns the URL of this instance"""
326        return self.absolute_url()
327   
328    def getStyle(self, idx, selected, style=""):
329        """returns a string with the given style and append 'sel' if idx == selected."""
330        #logger("documentViewer (getstyle)", logging.INFO, "idx: %s selected: %s style: %s"%(idx,selected,style))
331        if idx == selected:
332            return style + 'sel'
333        else:
334            return style
335   
336    def getParams(self, param=None, val=None, params=None, duplicates=None):
337        """returns dict with URL parameters.
338       
339        Takes URL parameters and additionally param=val or dict params.
340        Deletes key if value is None."""
341        # copy existing request params
342        newParams=self.REQUEST.form.copy()
343        # change single param
344        if param is not None:
345            if val is None:
346                if newParams.has_key(param):
347                    del newParams[param]
348            else:
349                newParams[param] = str(val)
350               
351        # change more params
352        if params is not None:
353            for (k, v) in params.items():
354                if v is None:
355                    # val=None removes param
356                    if newParams.has_key(k):
357                        del newParams[k]
358                       
359                else:
360                    newParams[k] = v
361
362        if duplicates:
363            # eliminate lists (coming from duplicate keys)
364            for (k,v) in newParams.items():
365                if isinstance(v, list):
366                    if duplicates == 'comma':
367                        # make comma-separated list of non-empty entries
368                        newParams[k] = ','.join([t for t in v if t])
369                    elif duplicates == 'first':
370                        # take first non-empty entry
371                        newParams[k] = [t for t in v if t][0]
372       
373        return newParams
374   
375    def getLink(self, param=None, val=None, params=None, baseUrl=None, paramSep='&', duplicates='comma'):
376        """returns URL to documentviewer with parameter param set to val or from dict params"""
377        urlParams = self.getParams(param=param, val=val, params=params, duplicates=duplicates)
378        # quote values and assemble into query string (not escaping '/')
379        ps = paramSep.join(["%s=%s"%(k,urllib.quote_plus(unicode(v),'/')) for (k, v) in urlParams.items()])
380        if baseUrl is None:
381            baseUrl = self.getDocumentViewerURL()
382           
383        url = "%s?%s"%(baseUrl, ps)
384        return url
385
386    def getLinkAmp(self, param=None, val=None, params=None, baseUrl=None, duplicates='comma'):
387        """link to documentviewer with parameter param set to val"""
388        return self.getLink(param=param, val=val, params=params, baseUrl=baseUrl, paramSep='&', duplicates=duplicates)
389   
390   
391    def getInfo_xml(self,url,mode):
392        """returns info about the document as XML"""
393        if not self.digilibBaseUrl:
394            self.digilibBaseUrl = self.findDigilibUrl() or "http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary"
395       
396        docinfo = self.getDocinfo(mode=mode,url=url)
397        pt = getattr(self.template, 'info_xml')
398        return pt(docinfo=docinfo)
399
400    def isAccessible(self, docinfo):
401        """returns if access to the resource is granted"""
402        access = docinfo.get('accessType', None)
403        logging.debug("documentViewer (accessOK) access type %s"%access)
404        if access == 'free':
405            logging.debug("documentViewer (accessOK) access is free")
406            return True
407       
408        elif access is None or access in self.authgroups:
409            # only local access -- only logged in users
410            user = getSecurityManager().getUser()
411            logging.debug("documentViewer (accessOK) user=%s ip=%s"%(user,self.REQUEST.getClientAddr()))
412            if user is not None:
413                #print "user: ", user
414                return (user.getUserName() != "Anonymous User")
415            else:
416                return False
417       
418        logging.error("documentViewer (accessOK) unknown access type %s"%access)
419        return False
420   
421
422
423    def getDocinfo(self, mode, url):
424        """returns docinfo depending on mode"""
425        logging.debug("getDocinfo: mode=%s, url=%s"%(mode,url))
426        # look for cached docinfo in session
427        if self.REQUEST.SESSION.has_key('docinfo'):
428            docinfo = self.REQUEST.SESSION['docinfo']
429            # check if its still current
430            if docinfo is not None and docinfo.get('mode', None) == mode and docinfo.get('url', None) == url:
431                logging.debug("getDocinfo: docinfo in session. keys=%s"%docinfo.keys())
432                return docinfo
433           
434        # new docinfo
435        docinfo = {'mode': mode, 'url': url}
436        # add self url
437        docinfo['viewerUrl'] = self.getDocumentViewerURL()
438        docinfo['digilibBaseUrl'] = self.digilibBaseUrl
439        # get index.meta DOM
440        docUrl = None
441        metaDom = None
442        if mode=="texttool": 
443            # url points to document dir or index.meta
444            metaDom = self.metadataService.getDomFromPathOrUrl(url)
445            docUrl = url.replace('/index.meta', '')
446            if metaDom is None:
447                raise IOError("Unable to find index.meta for mode=texttool!")
448
449        elif mode=="imagepath":
450            # url points to folder with images, index.meta optional
451            # asssume index.meta in parent dir
452            docUrl = getParentPath(url)
453            metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
454
455        elif mode=="filepath":
456            # url points to image file, index.meta optional
457            # asssume index.meta is two path segments up
458            docUrl = getParentPath(url, 2)
459            metaDom = self.metadataService.getDomFromPathOrUrl(docUrl)
460
461        else:
462            logging.error("documentViewer (getdocinfo) unknown mode: %s!"%mode)
463            raise ValueError("Unknown mode %s! Has to be one of 'texttool','imagepath','filepath'."%(mode))
464       
465        docinfo['documentUrl'] = docUrl
466        # process index.meta contents
467        if metaDom is not None and metaDom.tag == 'resource':
468            # document directory name and path
469            resource = self.metadataService.getResourceData(dom=metaDom)
470            if resource:
471                docinfo = self.getDocinfoFromResource(docinfo, resource)
472
473            # texttool info
474            texttool = self.metadataService.getTexttoolData(dom=metaDom)
475            if texttool:
476                docinfo = self.getDocinfoFromTexttool(docinfo, texttool)
477           
478            # bib info
479            bib = self.metadataService.getBibData(dom=metaDom)
480            if bib:
481                docinfo = self.getDocinfoFromBib(docinfo, bib)
482            else:
483                # no bib - try info.xml
484                docinfo = self.getDocinfoFromPresentationInfoXml(docinfo)
485               
486            # auth info
487            access = self.metadataService.getAccessData(dom=metaDom)
488            if access:
489                docinfo = self.getDocinfoFromAccess(docinfo, access)
490
491            # attribution info
492            attribution = self.metadataService.getAttributionData(dom=metaDom)
493            if attribution:
494                logging.debug("getDocinfo: attribution=%s"%repr(attribution))
495                docinfo['attribution'] = attribution
496                #docinfo = self.getDocinfoFromAccess(docinfo, access)
497
498            # copyright info
499            copyright = self.metadataService.getCopyrightData(dom=metaDom)
500            if copyright:
501                logging.debug("getDocinfo: copyright=%s"%repr(copyright))
502                docinfo['copyright'] = copyright
503                #docinfo = self.getDocinfoFromAccess(docinfo, access)
504
505        # image path
506        if mode != 'texttool':
507            # override image path from texttool with url
508            docinfo['imagePath'] = url.replace('/mpiwg/online/', '', 1)
509
510        # number of images from digilib
511        if docinfo.get('imagePath', None):
512            docinfo['imageURL'] = self.digilibBaseUrl + "/servlet/Scaler?fn=" + docinfo['imagePath']
513            docinfo = self.getDocinfoFromDigilib(docinfo, docinfo['imagePath'])
514
515        logging.debug("documentViewer (getdocinfo) docinfo: keys=%s"%docinfo.keys())
516        #logging.debug("documentViewer (getdocinfo) docinfo: %s"%docinfo)
517        # store in session
518        self.REQUEST.SESSION['docinfo'] = docinfo
519        return docinfo
520
521    def getDocinfoFromResource(self, docinfo, resource):
522        """reads contents of resource element into docinfo"""
523        docName = resource.get('name', None)
524        docinfo['documentName'] = docName
525        docPath = resource.get('archive-path', None)
526        if docPath:
527            # clean up document path
528            if docPath[0] != '/':
529                docPath = '/' + docPath
530               
531            if docName and (not docPath.endswith(docName)):
532                docPath += "/" + docName
533           
534        else:
535            # use docUrl as docPath
536            docUrl = docinfo['documentURL']
537            if not docUrl.startswith('http:'):
538                docPath = docUrl
539        if docPath:
540            # fix URLs starting with /mpiwg/online
541            docPath = docPath.replace('/mpiwg/online', '', 1)
542
543        docinfo['documentPath'] = docPath
544        return docinfo
545
546    def getDocinfoFromTexttool(self, docinfo, texttool):
547        """reads contents of texttool element into docinfo"""
548        # image dir
549        imageDir = texttool.get('image', None)
550        docPath = docinfo.get('documentPath', None)
551        if imageDir and docPath:
552            #print "image: ", imageDir, " archivepath: ", archivePath
553            imageDir = os.path.join(docPath, imageDir)
554            imageDir = imageDir.replace('/mpiwg/online', '', 1)
555            docinfo['imagePath'] = imageDir
556       
557        # old style text URL
558        textUrl = texttool.get('text', None)
559        if textUrl and docPath:
560            if urlparse.urlparse(textUrl)[0] == "": #keine url
561                textUrl = os.path.join(docPath, textUrl) 
562           
563            docinfo['textURL'] = textUrl
564   
565        # new style text-url-path
566        textUrl = texttool.get('text-url-path', None)
567        if textUrl:
568            docinfo['textURLPath'] = textUrl
569           
570        # page flow
571        docinfo['pageFlow'] = texttool.get('page-flow', 'ltr')
572           
573        # odd pages are left
574        docinfo['oddPage'] = texttool.get('odd-scan-position', 'left')
575           
576        # number of title page (0: not defined)
577        docinfo['titlePage'] = texttool.get('title-scan-no', 0)
578           
579        # old presentation stuff
580        presentation = texttool.get('presentation', None)
581        if presentation and docPath:
582            if presentation.startswith('http:'):
583                docinfo['presentationUrl'] = presentation
584            else:
585                docinfo['presentationUrl'] = os.path.join(docPath, presentation)
586           
587       
588        return docinfo
589
590    def getDocinfoFromBib(self, docinfo, bib):
591        """reads contents of bib element into docinfo"""
592        logging.debug("getDocinfoFromBib bib=%s"%repr(bib))
593        # put all raw bib fields in dict "bib"
594        docinfo['bib'] = bib
595        bibtype = bib.get('@type', None)
596        docinfo['bibType'] = bibtype
597        # also store DC metadata for convenience
598        dc = self.metadataService.getDCMappedData(bib)
599        docinfo['creator'] = dc.get('creator',None)
600        docinfo['title'] = dc.get('title',None)
601        docinfo['date'] = dc.get('date',None)
602        return docinfo
603           
604    def getDocinfoFromAccess(self, docinfo, acc):
605        """reads contents of access element into docinfo"""
606        #TODO: also read resource type
607        logging.debug("getDocinfoFromAccess acc=%s"%repr(acc))
608        try:
609            acctype = acc['@attr']['type']
610            if acctype:
611                access=acctype
612                if access in ['group', 'institution']:
613                    access = acc['name'].lower()
614               
615                docinfo['accessType'] = access
616
617        except:
618            pass
619       
620        return docinfo
621
622    def getDocinfoFromDigilib(self, docinfo, path):
623        infoUrl=self.digilibBaseUrl+"/dirInfo-xml.jsp?mo=dir&fn="+path
624        # fetch data
625        txt = getHttpData(infoUrl)
626        if not txt:
627            logging.error("Unable to get dir-info from %s"%(infoUrl))
628            return docinfo
629
630        dom = ET.fromstring(txt)
631        size = getText(dom.find("size"))
632        logging.debug("getDocinfoFromDigilib: size=%s"%size)
633        if size:
634            docinfo['numPages'] = int(size)
635        else:
636            docinfo['numPages'] = 0
637           
638        # TODO: produce and keep list of image names and numbers
639        return docinfo
640           
641           
642    def getDocinfoFromPresentationInfoXml(self,docinfo):
643        """gets DC-like bibliographical information from the presentation entry in texttools"""
644        url = docinfo.get('presentationUrl', None)
645        if not url:
646            logging.error("getDocinfoFromPresentation: no URL!")
647            return docinfo
648       
649        dom = None
650        metaUrl = None
651        if url.startswith("http://"):
652            # real URL
653            metaUrl = url
654        else:
655            # online path
656           
657            server=self.digilibBaseUrl+"/servlet/Texter?fn="
658            metaUrl=server+url
659       
660        txt=getHttpData(metaUrl)
661        if txt is None:
662            logging.error("Unable to read info.xml from %s"%(url))
663            return docinfo
664           
665        dom = ET.fromstring(txt)
666        docinfo['creator']=getText(dom.find(".//author"))
667        docinfo['title']=getText(dom.find(".//title"))
668        docinfo['date']=getText(dom.find(".//date"))
669        return docinfo
670   
671
672    def getPageinfo(self, current=None, start=None, rows=None, cols=None, docinfo=None, viewMode=None, viewLayer=None, tocMode=None):
673        """returns pageinfo with the given parameters"""
674        logging.debug("getPageInfo(current=%s, start=%s, rows=%s, cols=%s, viewMode=%s, viewLayer=%s, tocMode=%s)"%(current,start,rows,cols,viewMode,viewLayer,tocMode))
675        pageinfo = {}
676        pageinfo['viewMode'] = viewMode
677        pageinfo['viewLayer'] = viewLayer
678        pageinfo['tocMode'] = tocMode
679
680        current = getInt(current)
681        pageinfo['current'] = current
682        pageinfo['pn'] = current
683        rows = int(rows or self.thumbrows)
684        pageinfo['rows'] = rows
685        cols = int(cols or self.thumbcols)
686        pageinfo['cols'] = cols
687        grpsize = cols * rows
688        pageinfo['groupsize'] = grpsize
689        # is start is empty use one around current
690        start = getInt(start, default=(math.ceil(float(current)/float(grpsize))*grpsize-(grpsize-1)))
691        # int(current / grpsize) * grpsize +1))
692        pageinfo['start'] = start
693       
694        np = int(docinfo.get('numPages', 0))
695        if np == 0:
696            # numPages unknown - maybe we can get it from text page
697            if docinfo.get('textURLPath', None):
698                # cache text page as well
699                pageinfo['textPage'] = self.getTextPage(mode=viewLayer, pn=current, docinfo=docinfo, pageinfo=pageinfo)
700                np = int(docinfo.get('numPages', 0))
701               
702        pageinfo['numgroups'] = int(np / grpsize)
703        if np % grpsize > 0:
704            pageinfo['numgroups'] += 1
705
706        pageFlowLtr = docinfo.get('pageFlow', 'ltr') != 'rtl'
707        oddScanLeft = docinfo.get('oddPage', 'left') != 'right'
708        # add zeroth page for two columns
709        pageZero = (cols == 2 and (pageFlowLtr != oddScanLeft))
710        pageinfo['pageZero'] = pageZero
711        pageinfo['pageBatch'] = self.getPageBatch(start=start, rows=rows, cols=cols, pageFlowLtr=pageFlowLtr, pageZero=pageZero, minIdx=1, maxIdx=np)
712               
713        # TODO: do we need this here?
714        pageinfo['characterNormalization'] = self.REQUEST.get('characterNormalization','reg')
715        pageinfo['query'] = self.REQUEST.get('query','') 
716        pageinfo['queryType'] = self.REQUEST.get('queryType','')
717        pageinfo['querySearch'] =self.REQUEST.get('querySearch', 'fulltext')
718        pageinfo['highlightQuery'] = self.REQUEST.get('highlightQuery','')
719        pageinfo['tocPageSize'] = getInt(self.REQUEST.get('tocPageSize', 30))
720        pageinfo['queryPageSize'] = getInt(self.REQUEST.get('queryPageSize', 10))
721        pageinfo['tocPN'] = getInt(self.REQUEST.get('tocPN', '1'))
722        pageinfo['searchPN'] = getInt(self.REQUEST.get('searchPN','1'))
723       
724        # limit tocPN
725        if 'tocSize_%s'%tocMode in docinfo:
726            tocSize = docinfo['tocSize_%s'%tocMode]
727            tocPageSize = pageinfo['tocPageSize']
728            # cached toc           
729            if tocSize%tocPageSize>0:
730                tocPages=tocSize/tocPageSize+1
731            else:
732                tocPages=tocSize/tocPageSize
733               
734            pageinfo['tocPN'] = min(tocPages,pageinfo['tocPN'])
735           
736        return pageinfo
737
738
739    def getPageBatch(self, start=1, rows=10, cols=2, pageFlowLtr=True, pageZero=False, minIdx=1, maxIdx=0):
740        """returns dict with array of page informations for one screenfull of thumbnails"""
741        batch = {}
742        grpsize = rows * cols
743        if maxIdx == 0:
744            maxIdx = start + grpsize
745
746        nb = int(math.ceil(maxIdx / float(grpsize)))
747        # list of all batch start and end points
748        batches = []
749        if pageZero:
750            ofs = 0
751        else:
752            ofs = 1
753           
754        for i in range(nb):
755            s = i * grpsize + ofs
756            e = min((i + 1) * grpsize + ofs - 1, maxIdx)
757            batches.append({'start':s, 'end':e})
758           
759        batch['batches'] = batches
760
761        pages = []
762        if pageZero and start == 1:
763            # correct beginning
764            idx = 0
765        else:
766            idx = start
767           
768        for r in range(rows):
769            row = []
770            for c in range(cols):
771                if idx < minIdx or idx > maxIdx:
772                    page = {'idx':None}
773                else:
774                    page = {'idx':idx}
775                   
776                idx += 1
777                if pageFlowLtr:
778                    row.append(page)
779                else:
780                    row.insert(0, page) 
781               
782            pages.append(row)
783           
784        if start > 1:
785            batch['prevStart'] = max(start - grpsize, 1)
786        else:
787            batch['prevStart'] = None
788           
789        if start + grpsize < maxIdx:
790            batch['nextStart'] = start + grpsize
791        else:
792            batch['nextStart'] = None
793
794        batch['pages'] = pages
795        return batch
796       
797    def getBatch(self, start=1, size=10, end=0, data=None, fullData=True):
798        """returns dict with information for one screenfull of data."""
799        batch = {}
800        if end == 0:
801            end = start + size                   
802           
803        nb = int(math.ceil(end / float(size)))
804        # list of all batch start and end points
805        batches = []
806        for i in range(nb):
807            s = i * size + 1
808            e = min((i + 1) * size, end)
809            batches.append({'start':s, 'end':e})
810           
811        batch['batches'] = batches
812        # list of elements in this batch
813        this = []
814        j = 0
815        for i in range(start, min(start+size, end)):
816            if data:
817                if fullData:
818                    d = data[i]
819                else:
820                    d = data[j]
821                    j += 1
822           
823            else:
824                d = i+1
825               
826            this.append(d)
827           
828        batch['this'] = this
829        if start > 1:
830            batch['prevStart'] = max(start - size, 1)
831        else:
832            batch['prevStart'] = None
833           
834        if start + size < end:
835            batch['nextStart'] = start + size
836        else:
837            batch['nextStart'] = None
838       
839        return batch
840       
841
842    security.declareProtected('View management screens','changeDocumentViewerForm')   
843    changeDocumentViewerForm = PageTemplateFile('zpt/changeDocumentViewer', globals())
844   
845    def changeDocumentViewer(self,title="",digilibBaseUrl=None,thumbrows=2,thumbcols=5,authgroups='mpiwg',RESPONSE=None):
846        """init document viewer"""
847        self.title=title
848        self.digilibBaseUrl = digilibBaseUrl
849        self.thumbrows = thumbrows
850        self.thumbcols = thumbcols
851        self.authgroups = [s.strip().lower() for s in authgroups.split(',')]
852        try:
853            # assume MetaDataFolder instance is called metadata
854            self.metadataService = getattr(self, 'metadata')
855        except Exception, e:
856            logging.error("Unable to find MetaDataFolder 'metadata': "+str(e))
857
858        if RESPONSE is not None:
859            RESPONSE.redirect('manage_main')
860       
861def manage_AddDocumentViewerForm(self):
862    """add the viewer form"""
863    pt=PageTemplateFile('zpt/addDocumentViewer', globals()).__of__(self)
864    return pt()
865 
866def manage_AddDocumentViewer(self,id,imageScalerUrl="",textServerName="",title="",RESPONSE=None):
867    """add the viewer"""
868    newObj=documentViewer(id,imageScalerUrl=imageScalerUrl,title=title,textServerName=textServerName)
869    self._setObject(id,newObj)
870   
871    if RESPONSE is not None:
872        RESPONSE.redirect('manage_main')
Note: See TracBrowser for help on using the repository browser.