Annotation of zogiLib/zogiLib.py, revision 1.49
1.1 dwinter 1: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
2: from Products.PageTemplates.PageTemplate import PageTemplate
3: from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
1.4 dwinter 4: from OFS.Image import Image
5: from webdav.common import rfc1123_date
1.1 dwinter 6:
7: import xml.dom.minidom
8: from OFS.Folder import Folder
1.32 dwinter 9: from xml_helpers import getUniqueElementText,getText
1.1 dwinter 10: import os
11: import re
12: import string
13: import urllib
1.24 casties 14: import types
1.44 casties 15: import random
1.1 dwinter 16: from Globals import package_home
17:
1.49 ! casties 18: ZOGIVERSION = "0.9.11b ROC:12.10.2004"
1.30 casties 19:
20: def cropf(f):
21: """returns a float with reduced precision"""
22: return float(int(f * 10000)/10000.0)
23:
1.28 casties 24:
1.15 casties 25: def sendFile(self, filename, type):
1.44 casties 26: """sends an object or a local file (from the product) as response"""
1.17 casties 27: paths = filename.split('/')
28: object = self
29: # look for an object called filename
30: for path in paths:
31: if hasattr(object, path):
32: object = getattr(object, path)
33: else:
34: object = None
35: break
36: if object:
1.18 casties 37: # if the object exists then send it
38: return object.index_html(self.REQUEST.REQUEST, self.REQUEST.RESPONSE)
1.17 casties 39: else:
40: # send a local file with the given content-type
41: fn = os.path.join(package_home(globals()), filename)
42: self.REQUEST.RESPONSE.setHeader("Content-Type", type)
43: self.REQUEST.RESPONSE.write(file(fn).read())
1.15 casties 44: return
45:
1.26 casties 46: def browserCheck(self):
1.18 casties 47: """check the browsers request to find out the browser type"""
1.26 casties 48: bt = {}
49: ua = self.REQUEST.get_header("HTTP_USER_AGENT")
50: bt['ua'] = ua
51: bt['isIE'] = string.find(ua, 'MSIE') > -1
52: bt['isN4'] = (string.find(ua, 'Mozilla/4.') > -1) and not bt['isIE']
53: nav = ua[string.find(ua, '('):]
54: ie = string.split(nav, "; ")[1]
55: if string.find(ie, "MSIE") > -1:
56: bt['versIE'] = string.split(ie, " ")[1]
57: bt['isMac'] = string.find(ua, 'Macintosh') > -1
58: bt['isWin'] = string.find(ua, 'Windows') > -1
59: bt['isIEWin'] = bt['isIE'] and bt['isWin']
60: bt['isIEMac'] = bt['isIE'] and bt['isMac']
61: bt['staticHTML'] = False
1.5 dwinter 62:
1.26 casties 63: return bt
1.5 dwinter 64:
1.1 dwinter 65:
1.4 dwinter 66: class zogiImage(Image):
67: """einzelnes Image"""
68: meta_type="zogiImage"
69:
1.18 casties 70: manage_options=ZopePageTemplate.manage_options+(
71: {'label':'Main config','action':'changeZogiImageForm'},
72: )
1.4 dwinter 73:
74:
75: def __init__(self,id,title,baseUrl,queryString,content_type='',precondition=''):
76: """init"""
77: self.id=id
78: self.title=title
1.46 casties 79: if baseUrl:
80: self.baseUrl=baseUrl
81: else:
82: self.baseUrl="http://nausikaa.mpiwg-berlin.mpg.de/digitallibrary/servlet/Scaler?"
83:
1.4 dwinter 84: self.queryString=queryString
85: self.content_type=content_type
86: self.precondition=precondition
87:
88: def getData(self):
89: """getUrlData"""
90: return urllib.urlopen(self.baseUrl+self.queryString)
91:
92: def changeZogiImageForm(self):
93: """Main configuration"""
1.18 casties 94: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/changeZogiImageForm.zpt')).__of__(self)
1.4 dwinter 95: return pt()
96:
97: def changeZogiImage(self,title,baseUrl, queryString,RESPONSE=None):
98: """change it"""
99: self.title=title
100: self.baseUrl=baseUrl
101: self.queryString=queryString
102:
103: if RESPONSE is not None:
104: RESPONSE.redirect('manage_main')
105:
1.46 casties 106: def index_html(self, REQUEST, RESPONSE):
107: """service the request by redirecting to digilib server"""
108: RESPONSE.redirect(self.baseUrl+self.queryString)
109: return ''
1.4 dwinter 110:
1.46 casties 111: def index_html2(self, REQUEST, RESPONSE):
1.4 dwinter 112: """
113: Modified version of OFS/Image.py
1.1 dwinter 114:
1.4 dwinter 115: The default view of the contents of a File or Image.
116:
117: Returns the contents of the file or image. Also, sets the
118: Content-Type HTTP header to the objects content type.
119: """
120:
121: # HTTP If-Modified-Since header handling.
122: header=REQUEST.get_header('If-Modified-Since', None)
123: if header is not None:
124: header=header.split( ';')[0]
125: # Some proxies seem to send invalid date strings for this
126: # header. If the date string is not valid, we ignore it
127: # rather than raise an error to be generally consistent
128: # with common servers such as Apache (which can usually
129: # understand the screwy date string as a lucky side effect
130: # of the way they parse it).
131: # This happens to be what RFC2616 tells us to do in the face of an
132: # invalid date.
133: try: mod_since=long(DateTime(header).timeTime())
134: except: mod_since=None
135: if mod_since is not None:
136: if self._p_mtime:
137: last_mod = long(self._p_mtime)
138: else:
139: last_mod = long(0)
140: if last_mod > 0 and last_mod <= mod_since:
141: # Set header values since apache caching will return Content-Length
142: # of 0 in response if size is not set here
143: RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime))
144: RESPONSE.setHeader('Content-Type', self.content_type)
145: RESPONSE.setHeader('Content-Length', self.size)
146: RESPONSE.setHeader('Accept-Ranges', 'bytes')
147: self.ZCacheable_set(None)
148: RESPONSE.setStatus(304)
149: return ''
150:
151: if self.precondition and hasattr(self,self.precondition):
152: # Grab whatever precondition was defined and then
153: # execute it. The precondition will raise an exception
154: # if something violates its terms.
155: c=getattr(self,self.precondition)
156: if hasattr(c,'isDocTemp') and c.isDocTemp:
157: c(REQUEST['PARENTS'][1],REQUEST)
158: else:
159: c()
160:
161: # HTTP Range header handling
162: range = REQUEST.get_header('Range', None)
163: request_range = REQUEST.get_header('Request-Range', None)
164: if request_range is not None:
165: # Netscape 2 through 4 and MSIE 3 implement a draft version
166: # Later on, we need to serve a different mime-type as well.
167: range = request_range
168: if_range = REQUEST.get_header('If-Range', None)
169: if range is not None:
170: ranges = HTTPRangeSupport.parseRange(range)
171:
172: if if_range is not None:
173: # Only send ranges if the data isn't modified, otherwise send
174: # the whole object. Support both ETags and Last-Modified dates!
175: if len(if_range) > 1 and if_range[:2] == 'ts':
176: # ETag:
177: if if_range != self.http__etag():
178: # Modified, so send a normal response. We delete
179: # the ranges, which causes us to skip to the 200
180: # response.
181: ranges = None
182: else:
183: # Date
184: date = if_range.split( ';')[0]
185: try: mod_since=long(DateTime(date).timeTime())
186: except: mod_since=None
187: if mod_since is not None:
188: if self._p_mtime:
189: last_mod = long(self._p_mtime)
190: else:
191: last_mod = long(0)
192: if last_mod > mod_since:
193: # Modified, so send a normal response. We delete
194: # the ranges, which causes us to skip to the 200
195: # response.
196: ranges = None
197:
198: if ranges:
199: # Search for satisfiable ranges.
200: satisfiable = 0
201: for start, end in ranges:
202: if start < self.size:
203: satisfiable = 1
204: break
205:
206: if not satisfiable:
207: RESPONSE.setHeader('Content-Range',
208: 'bytes */%d' % self.size)
209: RESPONSE.setHeader('Accept-Ranges', 'bytes')
210: RESPONSE.setHeader('Last-Modified',
211: rfc1123_date(self._p_mtime))
212: RESPONSE.setHeader('Content-Type', self.content_type)
213: RESPONSE.setHeader('Content-Length', self.size)
214: RESPONSE.setStatus(416)
215: return ''
216:
217: ranges = HTTPRangeSupport.expandRanges(ranges, self.size)
218:
219: if len(ranges) == 1:
220: # Easy case, set extra header and return partial set.
221: start, end = ranges[0]
222: size = end - start
223:
224: RESPONSE.setHeader('Last-Modified',
225: rfc1123_date(self._p_mtime))
226: RESPONSE.setHeader('Content-Type', self.content_type)
227: RESPONSE.setHeader('Content-Length', size)
228: RESPONSE.setHeader('Accept-Ranges', 'bytes')
229: RESPONSE.setHeader('Content-Range',
230: 'bytes %d-%d/%d' % (start, end - 1, self.size))
231: RESPONSE.setStatus(206) # Partial content
232:
233: data = urllib.urlopen(self.baseUrl+self.queryString).read()
234: if type(data) is StringType:
235: return data[start:end]
236:
237: # Linked Pdata objects. Urgh.
238: pos = 0
239: while data is not None:
240: l = len(data.data)
241: pos = pos + l
242: if pos > start:
243: # We are within the range
244: lstart = l - (pos - start)
245:
246: if lstart < 0: lstart = 0
247:
248: # find the endpoint
249: if end <= pos:
250: lend = l - (pos - end)
251:
252: # Send and end transmission
253: RESPONSE.write(data[lstart:lend])
254: break
255:
256: # Not yet at the end, transmit what we have.
257: RESPONSE.write(data[lstart:])
258:
259: data = data.next
260:
261: return ''
262:
263: else:
264: boundary = choose_boundary()
265:
266: # Calculate the content length
267: size = (8 + len(boundary) + # End marker length
268: len(ranges) * ( # Constant lenght per set
269: 49 + len(boundary) + len(self.content_type) +
270: len('%d' % self.size)))
271: for start, end in ranges:
272: # Variable length per set
273: size = (size + len('%d%d' % (start, end - 1)) +
274: end - start)
275:
276:
277: # Some clients implement an earlier draft of the spec, they
278: # will only accept x-byteranges.
279: draftprefix = (request_range is not None) and 'x-' or ''
280:
281: RESPONSE.setHeader('Content-Length', size)
282: RESPONSE.setHeader('Accept-Ranges', 'bytes')
283: RESPONSE.setHeader('Last-Modified',
284: rfc1123_date(self._p_mtime))
285: RESPONSE.setHeader('Content-Type',
286: 'multipart/%sbyteranges; boundary=%s' % (
287: draftprefix, boundary))
288: RESPONSE.setStatus(206) # Partial content
289:
290: data = urllib.urlopen(self.baseUrl+self.queryString).read()
291: # The Pdata map allows us to jump into the Pdata chain
292: # arbitrarily during out-of-order range searching.
293: pdata_map = {}
294: pdata_map[0] = data
295:
296: for start, end in ranges:
297: RESPONSE.write('\r\n--%s\r\n' % boundary)
298: RESPONSE.write('Content-Type: %s\r\n' %
299: self.content_type)
300: RESPONSE.write(
301: 'Content-Range: bytes %d-%d/%d\r\n\r\n' % (
302: start, end - 1, self.size))
303:
304: if type(data) is StringType:
305: RESPONSE.write(data[start:end])
306:
307: else:
308: # Yippee. Linked Pdata objects. The following
309: # calculations allow us to fast-forward through the
310: # Pdata chain without a lot of dereferencing if we
311: # did the work already.
312: first_size = len(pdata_map[0].data)
313: if start < first_size:
314: closest_pos = 0
315: else:
316: closest_pos = (
317: ((start - first_size) >> 16 << 16) +
318: first_size)
319: pos = min(closest_pos, max(pdata_map.keys()))
320: data = pdata_map[pos]
321:
322: while data is not None:
323: l = len(data.data)
324: pos = pos + l
325: if pos > start:
326: # We are within the range
327: lstart = l - (pos - start)
328:
329: if lstart < 0: lstart = 0
330:
331: # find the endpoint
332: if end <= pos:
333: lend = l - (pos - end)
334:
335: # Send and loop to next range
336: RESPONSE.write(data[lstart:lend])
337: break
338:
339: # Not yet at the end, transmit what we have.
340: RESPONSE.write(data[lstart:])
341:
342: data = data.next
343: # Store a reference to a Pdata chain link so we
344: # don't have to deref during this request again.
345: pdata_map[pos] = data
346:
347: # Do not keep the link references around.
348: del pdata_map
349:
350: RESPONSE.write('\r\n--%s--\r\n' % boundary)
351: return ''
352:
353: RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime))
354: RESPONSE.setHeader('Content-Type', self.content_type)
355: RESPONSE.setHeader('Content-Length', self.size)
356: RESPONSE.setHeader('Accept-Ranges', 'bytes')
357:
358: # Don't cache the data itself, but provide an opportunity
359: # for a cache manager to set response headers.
360: self.ZCacheable_set(None)
361:
1.45 casties 362: #return "zogiimage: "+self.baseUrl+self.queryString
1.4 dwinter 363: data=urllib.urlopen(self.baseUrl+self.queryString).read()
364:
365: if type(data) is type(''):
366: RESPONSE.setBase(None)
367: return data
368:
369: while data is not None:
370: RESPONSE.write(data.data)
371: data=data.next
372:
373: return ''
374:
375:
376: def manage_addZogiImageForm(self):
377: """Form for adding"""
1.18 casties 378: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiImage.zpt')).__of__(self)
1.4 dwinter 379: return pt()
380:
381:
382: def manage_addZogiImage(self,id,title,baseUrl, queryString,RESPONSE=None):
1.46 casties 383: """add zogiimage"""
1.4 dwinter 384: newObj=zogiImage(id,title,baseUrl, queryString)
385: self.Destination()._setObject(id,newObj)
386: if RESPONSE is not None:
387: RESPONSE.redirect('manage_main')
388:
389:
390:
1.1 dwinter 391: class zogiLib(Folder):
392: """StandardElement"""
393:
394: meta_type="zogiLib"
1.32 dwinter 395: #xxxx
1.1 dwinter 396:
1.18 casties 397: manage_options = Folder.manage_options+(
398: {'label':'Main Config','action':'changeZogiLibForm'},
399: )
1.1 dwinter 400:
1.37 casties 401: def __init__(self, id, title, dlServerURL, layout="book", basePath="", dlTarget=None, dlToolbarBaseURL=None):
1.1 dwinter 402: """init"""
403:
404: self.id=id
405: self.title=title
1.34 casties 406: self.dlServerURL = dlServerURL
1.21 casties 407: self.basePath=basePath
1.37 casties 408: self.layout=layout
1.44 casties 409: self.dlTarget = dlTarget
1.1 dwinter 410:
1.37 casties 411: if dlToolbarBaseURL:
412: self.dlToolbarBaseURL = dlToolbarBaseURL
413: else:
414: self.dlToolbarBaseURL = dlServerURL + "/digimage.jsp?"
415:
416:
1.28 casties 417: def version(self):
418: """version information"""
419: return ZOGIVERSION
420:
1.32 dwinter 421: def getContextStatic(self):
422: """get all the contexts which go to static pages"""
423:
1.33 dwinter 424: try:
425: dom=xml.dom.minidom.parse(urllib.urlopen(self.getMetaFileName()))
426: contexts=dom.getElementsByTagName("context")
427:
428: ret=[]
429: for context in contexts:
430: name=getUniqueElementText(context.getElementsByTagName("name"))
431:
432: link=getUniqueElementText(context.getElementsByTagName("link"))
433: if name or link:
434: ret.append((name,link))
435: return ret
436: except:
437: return []
1.32 dwinter 438:
439: def getContextDatabases(self):
440: """get all dynamic contexts"""
1.33 dwinter 441: try:
442: dom=xml.dom.minidom.parse(urllib.urlopen(self.getMetaFileName()))
443: contexts=dom.getElementsByTagName("context")
444: ret=[]
445: for context in contexts:
446: metaDataLinks=context.getElementsByTagName("meta-datalink")
447: for metaDataLink in metaDataLinks:
448: db=metaDataLink.getAttribute("db")
449: link=self.REQUEST['URL1']+"/dl_db?db=%s"%db
450: if db:
451: ret.append((db,link))
452: metaDataLinks=context.getElementsByTagName("meta-baselink")
453:
454: for metaDataLink in metaDataLinks:
455: db=metaDataLink.getAttribute("db")
456: link=self.REQUEST['URL1']+"/dl_db?db=%s"%db
457: if db:
458: ret.append((db,link))
459:
460: return ret
461: except:
1.45 casties 462:
463: return []
1.32 dwinter 464:
1.39 casties 465:
1.32 dwinter 466: def formatHTML(self,url,label=None,viewUrl=None):
467:
468: sets=xml.dom.minidom.parse(urllib.urlopen(url)).getElementsByTagName('dataset')
469: ret=""
470: print label
471: if label:
472: ret+="""<a href="%s">%s</a>"""%(viewUrl,label)
473: for set in sets:
474: ret+="<table>"
475: for node in set.childNodes:
476: if hasattr(node,'tagName'):
477: tag=node.tagName
478: label=node.getAttribute("label")
479: if not label:
480: label=tag
481: text=getText(node.childNodes)
482: ret+="""<tr><td><b>%s:</b></td><td>%s</td></tr>"""%(label,text)
483: ret+="</table>"
484: return ret
1.39 casties 485:
1.32 dwinter 486:
487: def getMetaData(self):
488: """getMetaData"""
1.33 dwinter 489: try:
490: dom=xml.dom.minidom.parse(urllib.urlopen(self.getMetaFileName()))
491: except:
492: return "error metadata"
493:
1.32 dwinter 494: contexts=dom.getElementsByTagName("context")
495: ret=[]
496: db=self.getDLParam("db")
497: ob=self.getDLParam("object")
498:
499: fn=self.getDLParam("fn")
500: pn=self.getDLParam("pn")
501: if not fn:
502: fn=""
503: if not pn:
504: pn=""
505: if not ob:
506: ob=""
507:
508: for context in contexts:
509: metaDataLinks=context.getElementsByTagName("meta-datalink")
510: for metaDataLink in metaDataLinks:
511:
512: if (db==metaDataLink.getAttribute("db")) or (len(metaDataLinks)==1):
513:
514: link=getUniqueElementText(metaDataLink.getElementsByTagName("metadata-url"))
515: label=getUniqueElementText(metaDataLink.getElementsByTagName("label"))
516: url=getUniqueElementText(metaDataLink.getElementsByTagName("url"))
517:
518: return self.formatHTML(link,label,url)
519:
520: metaDataLinks=context.getElementsByTagName("meta-baselink")
521:
522: for metaDataLink in metaDataLinks:
523:
524: if db==metaDataLink.getAttribute("db") or (len(metaDataLinks)==1):
525:
526: link=getUniqueElementText(metaDataLink.getElementsByTagName("metadata-url"))
527: label=getUniqueElementText(metaDataLink.getElementsByTagName("label"))
528: url=getUniqueElementText(metaDataLink.getElementsByTagName("url"))
529:
530: return self.formatHTML(link+'fn=%s&pn=%s&object=%s'%(fn,pn,ob),label,url)
531: return ret
532:
1.39 casties 533:
1.18 casties 534: def getDLInfo(self):
535: """get DLInfo from digilib server"""
536: paramH={}
1.34 casties 537: baseUrl=self.dlServerURL+"/dlInfo-xml.jsp"
1.18 casties 538: try:
1.39 casties 539: url=urllib.urlopen(baseUrl+'?'+self.REQUEST['QUERY_STRING'])
1.18 casties 540: dom=xml.dom.minidom.parse(url)
541: params=dom.getElementsByTagName('parameter')
542: for param in params:
543: paramH[param.getAttribute('name')]=param.getAttribute('value')
544: return paramH
545: except:
1.34 casties 546: return {}
1.18 casties 547:
1.1 dwinter 548:
1.18 casties 549: def createHeadJS(self):
1.19 casties 550: """generate all javascript tags for head"""
1.26 casties 551: self.checkQuery()
1.44 casties 552: bt = self.REQUEST.SESSION.get('browserType', {})
1.26 casties 553: if bt['staticHTML']:
554: return
555:
1.18 casties 556: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogilib_head_js')).__of__(self)
557: return pt()
1.19 casties 558:
559: def createParamJS(self):
560: """generate javascript for parameters only"""
1.26 casties 561: self.checkQuery()
562: bt = self.REQUEST.SESSION['browserType']
563: if bt['staticHTML']:
564: return
565:
1.19 casties 566: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogilib_param_js')).__of__(self)
567: return pt()
568:
1.3 dwinter 569:
1.26 casties 570: def createScalerImg(self, requestString=None, bottom=0, side=0, width=500, height=500):
1.18 casties 571: """generate Scaler IMG Tag"""
1.20 casties 572: self.checkQuery()
573: bt = self.REQUEST.SESSION['browserType']
1.24 casties 574: # override with parameters from session
575: if self.REQUEST.SESSION.has_key('scalerDiv'):
1.26 casties 576: (requestString, bottom, side, width, height) = self.REQUEST.SESSION['scalerDiv']
1.24 casties 577: # if not explicitly defined take normal request
1.18 casties 578: if not requestString:
1.21 casties 579: requestString = self.getAllDLParams()
1.35 casties 580: url = self.dlServerURL+'/servlet/Scaler?'+requestString
1.24 casties 581: # construct bottom and side insets
582: b_par = ""
583: s_par = ""
584: if (bottom != 0) or (side != 0):
585: b_par = "-" + str(int(bottom))
586: s_par = "-" + str(int(side))
1.18 casties 587: tag = ""
1.26 casties 588: if bt['staticHTML']:
589: tag += '<div id="scaler"><img id="pic" src="%s&dw=%i&dh=%i" /></div>'%(url, int(width-side), int(height-bottom))
1.18 casties 590: else:
1.26 casties 591: if bt['isN4']:
592: # N4 needs layers
593: tag += '<ilayer id="scaler">'
594: else:
595: tag += '<div id="scaler">'
596: tag += '<script type="text/javascript">'
597: tag += "var ps = bestPicSize(getElement('scaler'));"
598: # write img tag with javascript
599: tag += 'document.write(\'<img id="pic" src="%s&dw=\'+(ps.width%s)+\'&dh=\'+(ps.height%s)+\'" />\');'%(url, s_par, b_par)
600: tag += '</script>'
601: if bt['isN4']:
602: tag += '</ilayer>'
603: else:
604: tag += '</div>'
1.18 casties 605: return tag
1.1 dwinter 606:
1.26 casties 607: def createScalerDiv(self, requestString = None, bottom = 0, side = 0, width=500, height=500):
1.23 casties 608: """generate scaler img and table with navigation arrows"""
609: self.checkQuery()
1.24 casties 610: if requestString != None or bottom != 0 or side != 0:
1.26 casties 611: self.REQUEST.SESSION['scalerDiv'] = (requestString, bottom, side, width, height)
1.24 casties 612: else:
613: if self.REQUEST.SESSION.has_key('scalerDiv'):
1.26 casties 614: # make shure to remove unused parameter
1.24 casties 615: del self.REQUEST.SESSION['scalerDiv']
1.26 casties 616:
1.23 casties 617: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt/zogilib_img_div')).__of__(self)
618: return pt()
619:
1.18 casties 620: def createAuxDiv(self):
621: """generate other divs"""
1.20 casties 622: self.checkQuery()
623: bt = self.REQUEST.SESSION['browserType']
1.26 casties 624: if bt['staticHTML']:
625: return
626: if bt['isN4']:
1.18 casties 627: f = 'zpt/zogilib_divsN4.zpt'
628: else:
629: f = 'zpt/zogilib_divs.zpt'
630: pt=PageTemplateFile(os.path.join(package_home(globals()),f)).__of__(self)
631: return pt()
1.3 dwinter 632:
1.9 dwinter 633:
1.18 casties 634: def option_js(self):
1.28 casties 635: """javascript"""
636: return sendFile(self, 'js/option.js', 'text/plain')
1.1 dwinter 637:
1.18 casties 638: def dl_lib_js(self):
639: """javascript"""
1.34 casties 640: return sendFile(self, 'js/dllib.js', 'text/plain')
1.18 casties 641:
642: def js_lib_js(self):
643: """javascript"""
1.34 casties 644: return sendFile(self, 'js/baselib.js', 'text/plain')
1.1 dwinter 645:
1.18 casties 646: def optionwindow(self):
647: """showoptions"""
1.26 casties 648: self.checkQuery()
649: bt = self.REQUEST.SESSION['browserType']
650: if bt['staticHTML']:
651: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/optionwindow_static.zpt')).__of__(self)
652: else:
1.37 casties 653: tp = "viewingTools.zpt"
654: if hasattr(self, tp):
655: pt = getattr(self, tp)
1.31 dwinter 656: else:
657: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/optionwindow.zpt')).__of__(self)
1.37 casties 658:
659: return pt()
1.13 casties 660:
661: def mark1(self):
662: """mark image"""
1.18 casties 663: return sendFile(self, 'images/mark1.gif', 'image/gif')
1.13 casties 664:
665: def mark2(self):
666: """mark image"""
1.18 casties 667: return sendFile(self, 'images/mark2.gif', 'image/gif')
1.13 casties 668:
669: def mark3(self):
670: """mark image"""
1.18 casties 671: return sendFile(self, 'images/mark3.gif', 'image/gif')
1.13 casties 672:
673: def mark4(self):
674: """mark image"""
1.18 casties 675: return sendFile(self, 'images/mark4.gif', 'image/gif')
1.13 casties 676:
677: def mark5(self):
678: """mark image"""
1.18 casties 679: return sendFile(self, 'images/mark5.gif', 'image/gif')
1.13 casties 680:
681: def mark6(self):
682: """mark image"""
1.18 casties 683: return sendFile(self, 'images/mark6.gif', 'image/gif')
1.13 casties 684:
685: def mark7(self):
686: """mark image"""
1.18 casties 687: return sendFile(self, 'images/mark7.gif', 'image/gif')
1.13 casties 688:
689: def mark8(self):
690: """mark image"""
1.18 casties 691: return sendFile(self, 'images/mark8.gif', 'image/gif')
1.13 casties 692:
693: def corner1(self):
694: """mark image"""
1.18 casties 695: return sendFile(self, 'images/olinks.gif', 'image/gif')
1.13 casties 696:
697: def corner2(self):
698: """mark image"""
1.18 casties 699: return sendFile(self, 'images/orechts.gif', 'image/gif')
1.13 casties 700:
701: def corner3(self):
702: """mark image"""
1.18 casties 703: return sendFile(self, 'images/ulinks.gif', 'image/gif')
1.13 casties 704:
705: def corner4(self):
706: """mark image"""
1.18 casties 707: return sendFile(self, 'images/urechts.gif', 'image/gif')
1.13 casties 708:
1.22 casties 709: def up_img(self):
710: """mark image"""
711: return sendFile(self, 'images/up.gif', 'image/gif')
712:
713: def down_img(self):
714: """mark image"""
715: return sendFile(self, 'images/down.gif', 'image/gif')
716:
717: def left_img(self):
718: """mark image"""
719: return sendFile(self, 'images/left.gif', 'image/gif')
720:
721: def right_img(self):
722: """mark image"""
723: return sendFile(self, 'images/right.gif', 'image/gif')
1.13 casties 724:
725:
1.1 dwinter 726:
727: def index_html(self):
728: """main action"""
1.26 casties 729: self.checkQuery()
730: bt = self.REQUEST.SESSION['browserType']
1.18 casties 731: tp = "zogiLibMainTemplate"
1.32 dwinter 732:
1.18 casties 733: if hasattr(self, tp):
734: pt = getattr(self, tp)
735: else:
1.26 casties 736: tpt = self.layout
1.32 dwinter 737:
1.26 casties 738: if bt['staticHTML']:
739: tpt = "static"
740:
741: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogiLibMain_%s'%tpt)).__of__(self)
742:
1.18 casties 743: return pt()
744:
1.1 dwinter 745:
1.21 casties 746: def storeQuery(self, more = None):
1.1 dwinter 747: """storeQuery in session"""
1.18 casties 748: dlParams = {}
1.1 dwinter 749: for fm in self.REQUEST.form.keys():
1.18 casties 750: dlParams[fm] = self.REQUEST.form[fm]
1.21 casties 751: # look for more
752: if more:
753: for fm in more.split('&'):
754: try:
755: pv = fm.split('=')
756: dlParams[pv[0]] = pv[1]
757: except:
1.26 casties 758: pass
759:
1.21 casties 760: # parse digilib mode parameter
1.18 casties 761: if 'mo' in dlParams:
762: if len(dlParams['mo']) > 0:
763: modes=dlParams['mo'].split(',')
764: else:
765: modes=[]
1.44 casties 766:
767: wid = self.getWID()
768: self.REQUEST.set('wid', wid)
769: self.setSubSession('dlQuery', dlParams)
770: self.setSubSession('dlModes', modes)
771: self.setSubSession('dlInfo', self.getDLInfo())
1.26 casties 772: if not self.REQUEST.SESSION.has_key('browserType'):
773: self.REQUEST.SESSION['browserType'] = browserCheck(self)
774:
775: return
1.1 dwinter 776:
1.20 casties 777: def checkQuery(self):
778: """check if the query has been stored"""
1.44 casties 779: if not (self.REQUEST.SESSION and self.getSubSession('dlQuery')) :
1.20 casties 780: print "ZOGILIB: have to store query!!"
1.26 casties 781: self.storeQuery()
1.24 casties 782: return
1.23 casties 783:
1.24 casties 784: def zogilibPath(self, otherbase=None):
1.23 casties 785: """returns an URL to the zogiLib instance"""
786: url = self.REQUEST['URL1']
1.24 casties 787: # should end with "/"
788: if len(url) > 0 and url[-1] != '/':
789: url += '/'
790: if type(otherbase) is str:
791: url += otherbase
792: else:
793: url += self.basePath
1.23 casties 794: # should end with "/"
795: if len(url) > 0 and url[-1] != '/':
796: url += '/'
797: return url
1.44 casties 798:
799: def zogilibAction(self, action, otherbase=None, wid=None):
800: """returns a URL with zogilib path, action and wid"""
801: url = self.zogilibPath(otherbase)
802: url += action
803: if wid:
804: url += '?wid=' + wid
805: else:
806: url += '?wid=' + self.getWID()
807: return url
808:
809: def getSubSession(self, key, default=None):
810: """returns an element from a session with a wid"""
811: wid = self.getWID()
812: return self.REQUEST.SESSION.get(key+'_'+wid, default)
813:
814: def setSubSession(self, key, value):
815: """puts an element in a session with a wid"""
816: wid = self.getWID()
817: self.REQUEST.SESSION.set(key+'_'+wid, value)
818: return
819:
820: def getWID(self):
821: """returns a (new) window id"""
822: wid = self.REQUEST.get('wid')
823: if not wid:
824: wid = 'digi_'+str(int(random.random()*10000))
825: print "new WID:", wid
826: return wid
1.3 dwinter 827:
1.22 casties 828: def getDLParam(self, param):
1.18 casties 829: """returns parameter"""
1.3 dwinter 830: try:
1.44 casties 831: return self.getSubSession('dlQuery').get(param)
1.3 dwinter 832: except:
1.24 casties 833: return
1.3 dwinter 834:
1.18 casties 835: def setDLParam(self, param, value):
836: """sets parameter"""
1.44 casties 837: dlParams = self.getSubSession('dlQuery')
838: #try:
839: dlParams[param] = value
840: #except:
841: # self.setSubSession('dlQuery', {param: value})
1.18 casties 842: return
843:
844: def getAllDLParams(self):
845: """parameter string for digilib"""
1.44 casties 846: dlParams = self.getSubSession('dlQuery')
1.18 casties 847: # save modes
1.44 casties 848: modes = self.getSubSession('dlModes')
1.18 casties 849: dlParams['mo'] = string.join(modes, ',')
850: # assemble query string
851: ret = ""
852: for param in dlParams.keys():
1.29 casties 853: if dlParams[param] is None: continue
1.18 casties 854: val = str(dlParams[param])
855: if val != "":
856: ret += param + "=" + val + "&"
1.28 casties 857:
1.18 casties 858: # omit trailing "&"
859: return ret.rstrip('&')
860:
861:
862: def setDLParams(self,pn=None,ws=None,rot=None,brgt=None,cont=None):
863: """setze Parameter"""
864:
1.23 casties 865: self.setDLParam('brgt', brgt)
866: self.setDLParam('cont', cont)
867: self.setDLParam('ws', ws)
868: self.setDLParam('rot', rot)
1.18 casties 869:
870: if pn:
1.21 casties 871: # unmark
872: self.setDLParam('mk', None)
1.18 casties 873: self.setDLParam('pn', pn)
874:
875: return self.display()
876:
877:
878: def display(self):
879: """(re)display page"""
1.44 casties 880: if not self.getDLParam('wid'):
881: wid = self.getWID()
882: self.setDLParam('wid', wid)
883:
1.18 casties 884: params = self.getAllDLParams()
1.44 casties 885:
1.21 casties 886: if self.basePath:
887: self.REQUEST.RESPONSE.redirect(self.REQUEST['URL2']+'?'+params)
888: else:
889: self.REQUEST.RESPONSE.redirect(self.REQUEST['URL1']+'?'+params)
1.18 casties 890:
1.32 dwinter 891: def getMetaFileName(self):
1.34 casties 892: url=self.dlServerURL+'/dlContext-xml.jsp?'+self.getAllDLParams()
893: return urlbase
1.26 casties 894:
1.34 casties 895: def getToolbarPageURL(self):
896: """returns a toolbar-enabled page URL"""
1.37 casties 897: url=self.dlToolbarBaseURL+self.getAllDLParams()
1.34 casties 898: return url
1.32 dwinter 899:
1.30 casties 900: def getDLTarget(self):
901: """returns dlTarget"""
902: self.checkQuery()
903: s = self.dlTarget
1.44 casties 904: if s == None:
905: s = ""
1.30 casties 906: # s = 'dl'
907: # if self.getDLParam('fn'):
908: # s += "_" + self.getDLParam('fn')
909: # if self.getDLParam('pn'):
910: # s += "_" + self.getDLParam('pn')
911: return s
912:
1.26 casties 913: def setStaticHTML(self, static=True):
914: """sets the preference to static HTML"""
915: self.checkQuery()
916: self.REQUEST.SESSION['browserType']['staticHTML'] = static
917: return
918:
919: def isStaticHTML(self):
920: """returns if the page is using static HTML only"""
921: self.checkQuery()
922: return self.REQUEST.SESSION['browserType']['staticHTML']
923:
1.18 casties 924: def getPT(self):
925: """pagenums"""
1.47 casties 926: di = self.getSubSession('dlInfo')
1.18 casties 927: if di:
928: return int(di['pt'])
929: else:
930: return 1
931:
932: def getPN(self):
933: """Pagenum"""
934: pn = self.getDLParam('pn')
1.25 casties 935: try:
1.18 casties 936: return int(pn)
1.25 casties 937: except:
1.3 dwinter 938: return 1
939:
1.18 casties 940: def getBiggerWS(self):
1.3 dwinter 941: """ws+1"""
1.23 casties 942: ws = self.getDLParam('ws')
1.25 casties 943: try:
1.26 casties 944: return float(ws)+0.5
1.25 casties 945: except:
1.26 casties 946: return 1.5
1.3 dwinter 947:
1.18 casties 948: def getSmallerWS(self):
949: """ws-1"""
950: ws=self.getDLParam('ws')
1.25 casties 951: try:
1.26 casties 952: return max(float(ws)-0.5, 1)
1.25 casties 953: except:
1.3 dwinter 954: return 1
1.1 dwinter 955:
1.18 casties 956: def hasMode(self, mode):
957: """returns if mode is in the diglib mo parameter"""
1.44 casties 958: wid = self.getWID()
959: return (mode in self.REQUEST.SESSION['dlModes_'+wid])
1.18 casties 960:
961: def hasNextPage(self):
962: """returns if there is a next page"""
963: pn = self.getPN()
964: pt = self.getPT()
965: return (pn < pt)
966:
967: def hasPrevPage(self):
968: """returns if there is a previous page"""
969: pn = self.getPN()
970: return (pn > 1)
1.1 dwinter 971:
1.22 casties 972: def canMoveLeft(self):
973: """returns if its possible to move left"""
974: wx = float(self.getDLParam('wx') or 0)
975: return (wx > 0)
976:
977: def canMoveRight(self):
978: """returns if its possible to move right"""
979: wx = float(self.getDLParam('wx') or 0)
980: ww = float(self.getDLParam('ww') or 1)
981: return (wx + ww < 1)
982:
983: def canMoveUp(self):
984: """returns if its possible to move up"""
985: wy = float(self.getDLParam('wy') or 0)
986: return (wy > 0)
987:
988: def canMoveDown(self):
989: """returns if its possible to move down"""
990: wy = float(self.getDLParam('wy') or 0)
991: wh = float(self.getDLParam('wh') or 1)
992: return (wy + wh < 1)
993:
1.26 casties 994:
995: def dl_StaticHTML(self):
996: """set rendering to static HTML"""
997: self.checkQuery()
998: self.REQUEST.SESSION['browserType']['staticHTML'] = True
999: return self.display()
1000:
1001: def dl_DynamicHTML(self):
1002: """set rendering to dynamic HTML"""
1003: self.checkQuery()
1004: self.REQUEST.SESSION['browserType']['staticHTML'] = False
1005: return self.display()
1.1 dwinter 1006:
1.18 casties 1007: def dl_HMirror(self):
1008: """mirror action"""
1.44 casties 1009: modes = self.getSubSession('dlModes')
1.18 casties 1010: if 'hmir' in modes:
1011: modes.remove('hmir')
1012: else:
1013: modes.append('hmir')
1.1 dwinter 1014:
1.18 casties 1015: return self.display()
1016:
1017: def dl_VMirror(self):
1018: """mirror action"""
1.44 casties 1019: modes = self.getSubSession('dlModes')
1.18 casties 1020: if 'vmir' in modes:
1021: modes.remove('vmir')
1022: else:
1023: modes.append('vmir')
1.1 dwinter 1024:
1.18 casties 1025: return self.display()
1.1 dwinter 1026:
1.22 casties 1027: def dl_Zoom(self, z):
1028: """general zoom action"""
1029: ww1 = float(self.getDLParam('ww') or 1)
1030: wh1 = float(self.getDLParam('wh') or 1)
1031: wx = float(self.getDLParam('wx') or 0)
1032: wy = float(self.getDLParam('wy') or 0)
1033: ww2 = ww1 * z
1034: wh2 = wh1 * z
1035: wx += (ww1 - ww2) / 2
1036: wy += (wh1 - wh2) / 2
1037: ww2 = max(min(ww2, 1), 0)
1038: wh2 = max(min(wh2, 1), 0)
1039: wx = max(min(wx, 1), 0)
1040: wy = max(min(wy, 1), 0)
1.30 casties 1041: self.setDLParam('ww', cropf(ww2))
1042: self.setDLParam('wh', cropf(wh2))
1043: self.setDLParam('wx', cropf(wx))
1044: self.setDLParam('wy', cropf(wy))
1.22 casties 1045: return self.display()
1046:
1047: def dl_ZoomIn(self):
1048: """zoom in action"""
1049: z = 0.7071
1050: return self.dl_Zoom(z)
1051:
1052: def dl_ZoomOut(self):
1053: """zoom out action"""
1054: z = 1.4142
1055: return self.dl_Zoom(z)
1056:
1057: def dl_Move(self, dx, dy):
1058: """general move action"""
1059: ww = float(self.getDLParam('ww') or 1)
1060: wh = float(self.getDLParam('wh') or 1)
1061: wx = float(self.getDLParam('wx') or 0)
1062: wy = float(self.getDLParam('wy') or 0)
1063: wx += dx * 0.5 * ww
1064: wy += dy * 0.5 * wh
1065: wx = max(min(wx, 1), 0)
1066: wy = max(min(wy, 1), 0)
1.30 casties 1067: self.setDLParam('wx', cropf(wx))
1068: self.setDLParam('wy', cropf(wy))
1.22 casties 1069: return self.display()
1070:
1071: def dl_MoveLeft(self):
1072: """move left action"""
1073: return self.dl_Move(-1, 0)
1074:
1075: def dl_MoveRight(self):
1076: """move left action"""
1077: return self.dl_Move(1, 0)
1078:
1079: def dl_MoveUp(self):
1080: """move left action"""
1081: return self.dl_Move(0, -1)
1082:
1083: def dl_MoveDown(self):
1084: """move left action"""
1085: return self.dl_Move(0, 1)
1086:
1.18 casties 1087: def dl_WholePage(self):
1088: """zoom out action"""
1089: self.setDLParam('ww', 1)
1090: self.setDLParam('wh', 1)
1091: self.setDLParam('wx', 0)
1092: self.setDLParam('wy', 0)
1093: return self.display()
1094:
1095: def dl_PrevPage(self):
1096: """next page action"""
1097: pn = self.getPN() - 1
1098: if pn < 1:
1099: pn = 1
1100: self.setDLParam('pn', pn)
1101: # unmark
1102: self.setDLParam('mk', None)
1103: return self.display()
1104:
1105: def dl_NextPage(self):
1106: """next page action"""
1107: pn = self.getPN() + 1
1108: pt = self.getPT()
1109: if pn > pt:
1110: pn = pt
1111: self.setDLParam('pn', pn)
1112: # unmark
1113: self.setDLParam('mk', None)
1114: return self.display()
1115:
1116: def dl_FirstPage(self):
1117: """first page action"""
1118: self.setDLParam('pn', 1)
1119: # unmark
1120: self.setDLParam('mk', None)
1121: return self.display()
1122:
1123: def dl_LastPage(self):
1124: """last page action"""
1125: self.setDLParam('pn', self.getPT())
1126: # unmark
1127: self.setDLParam('mk', None)
1128: return self.display()
1129:
1130: def dl_Unmark(self):
1131: """action to remove last mark"""
1132: mk = self.getDLParam('mk')
1133: if mk:
1134: marks = mk.split(',')
1135: marks.pop()
1136: mk = string.join(marks, ',')
1137: self.setDLParam('mk', mk)
1138: return self.display()
1.1 dwinter 1139:
1.32 dwinter 1140: def dl_db(self,db):
1141: """set db"""
1142: self.setDLParam('db',db)
1143: self.display()
1.1 dwinter 1144:
1.18 casties 1145: def changeZogiLibForm(self):
1146: """Main configuration"""
1147: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/changeZogiLibForm.zpt')).__of__(self)
1148: return pt()
1.1 dwinter 1149:
1.37 casties 1150: def changeZogiLib(self,title,dlServerURL, version, basePath, dlTarget, dlToolbarBaseURL, RESPONSE=None):
1.18 casties 1151: """change it"""
1152: self.title=title
1.35 casties 1153: self.dlServerURL=dlServerURL
1.21 casties 1154: self.basePath = basePath
1.18 casties 1155: self.layout=version
1.44 casties 1156: self.dlTarget = dlTarget
1.3 dwinter 1157:
1.37 casties 1158: if dlToolbarBaseURL:
1159: self.dlToolbarBaseURL = dlToolbarBaseURL
1160: else:
1161: self.dlToolbarBaseURL = dlServerURL + "/digimage.jsp?"
1162:
1.18 casties 1163: if RESPONSE is not None:
1164: RESPONSE.redirect('manage_main')
1.8 dwinter 1165:
1.35 casties 1166:
1167:
1168: ##
1.44 casties 1169: ## odds and ends
1.35 casties 1170: ##
1171:
1172: def repairZogilib(self, obj=None):
1173: """change stuff that broke on upgrading"""
1174:
1175: msg = ""
1176:
1177: if not obj:
1178: obj = self.getPhysicalRoot()
1179:
1180: print "starting in ", obj
1181:
1182: entries=obj.ZopeFind(obj,obj_metatypes=['zogiLib'],search_sub=1)
1183:
1184: for entry in entries:
1185: print " found ", entry
1.37 casties 1186: #
1187: # replace digilibBaseUrl by dlServerURL
1.35 casties 1188: if hasattr(entry[1], 'digilibBaseUrl'):
1.37 casties 1189: msg += " fixing digilibBaseUrl in "+entry[0]+"\n"
1.36 casties 1190: entry[1].dlServerURL = re.sub('/servlet/Scaler\?','',entry[1].digilibBaseUrl)
1.35 casties 1191: del entry[1].digilibBaseUrl
1192:
1.37 casties 1193: #
1194: # add dlToolbarBaseURL
1195: if not hasattr(entry[1], 'dlToolbarBaseURL'):
1196: msg += " fixing dlToolbarBaseURL in "+entry[0]+"\n"
1197: entry[1].dlToolbarBaseURL = entry[1].dlServerURL + "/digimage.jsp?"
1198:
1.35 casties 1199: return msg+"\n\nfixed all zogilib instances in: "+obj.title
1200:
1.8 dwinter 1201:
1.1 dwinter 1202: def manage_addZogiLibForm(self):
1203: """interface for adding zogilib"""
1.18 casties 1204: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiLibForm')).__of__(self)
1.1 dwinter 1205: return pt()
1206:
1.44 casties 1207: def manage_addZogiLib(self,id,title,dlServerURL,version="book",basePath="",dlTarget=None,dlToolbarBaseURL=None,RESPONSE=None):
1.1 dwinter 1208: """add dgilib"""
1.43 casties 1209: newObj=zogiLib(id,title,dlServerURL, version, basePath, dlTarget, dlToolbarBaseURL)
1.1 dwinter 1210: self.Destination()._setObject(id,newObj)
1211: if RESPONSE is not None:
1212: RESPONSE.redirect('manage_main')
1.29 casties 1213:
1214:
1215: class zogiLibPageTemplate(ZopePageTemplate):
1216: """pageTemplate Objekt"""
1217: meta_type="zogiLib_pageTemplate"
1218:
1219:
1220: ## def __init__(self, id, text=None, contentType=None):
1221: ## self.id = str(id)
1222: ## self.ZBindings_edit(self._default_bindings)
1223: ## if text is None:
1224: ## text = open(self._default_cont).read()
1225: ## self.pt_edit(text, contentType)
1226:
1227: def manage_addZogiLibPageTemplateForm(self):
1228: """Form for adding"""
1229: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiLibPageTemplateForm')).__of__(self)
1230: return pt()
1231:
1232: def manage_addZogiLibPageTemplate(self, id='zogiLibMainTemplate', title=None, layout=None, text=None,
1233: REQUEST=None, submit=None):
1234: "Add a Page Template with optional file content."
1235:
1236: id = str(id)
1237: self._setObject(id, zogiLibPageTemplate(id))
1238: ob = getattr(self, id)
1239: if not layout: layout = "book"
1240: ob.pt_edit(open(os.path.join(package_home(globals()),'zpt/zogiLibMain_%s.zpt'%layout)).read(),None)
1241: if title:
1242: ob.pt_setTitle(title)
1243: try:
1244: u = self.DestinationURL()
1245: except AttributeError:
1246: u = REQUEST['URL1']
1247:
1248: u = "%s/%s" % (u, urllib.quote(id))
1249: REQUEST.RESPONSE.redirect(u+'/manage_main')
1250: return ''
1.35 casties 1251:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>