Annotation of zogiLib/zogiLib.py, revision 1.30
1.13 casties 1:
1.1 dwinter 2: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
3: from Products.PageTemplates.PageTemplate import PageTemplate
4: from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
1.4 dwinter 5: from OFS.Image import Image
6: from webdav.common import rfc1123_date
1.1 dwinter 7:
8: import xml.dom.minidom
9: from OFS.Folder import Folder
10: from xml_helpers import getText
11: import os
12: import re
13: import string
14: import urllib
1.24 casties 15: import types
1.1 dwinter 16: from Globals import package_home
17:
1.30 ! casties 18: ZOGIVERSION = "0.9.5 ROC:25.6.2004"
! 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.17 casties 26: """sends an object or a local file (in the product) as response"""
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
79: self.baseUrl=baseUrl
80: self.queryString=queryString
81: self.content_type=content_type
82: self.precondition=precondition
83:
84: def getData(self):
85: """getUrlData"""
86: return urllib.urlopen(self.baseUrl+self.queryString)
87:
88: def changeZogiImageForm(self):
89: """Main configuration"""
1.18 casties 90: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/changeZogiImageForm.zpt')).__of__(self)
1.4 dwinter 91: return pt()
92:
93: def changeZogiImage(self,title,baseUrl, queryString,RESPONSE=None):
94: """change it"""
95: self.title=title
96: self.baseUrl=baseUrl
97: self.queryString=queryString
98:
99: if RESPONSE is not None:
100: RESPONSE.redirect('manage_main')
101:
102:
103: def index_html(self, REQUEST, RESPONSE):
104: """
105: Modified version of OFS/Image.py
1.1 dwinter 106:
1.4 dwinter 107: The default view of the contents of a File or Image.
108:
109: Returns the contents of the file or image. Also, sets the
110: Content-Type HTTP header to the objects content type.
111: """
112:
113: # HTTP If-Modified-Since header handling.
114: header=REQUEST.get_header('If-Modified-Since', None)
115: if header is not None:
116: header=header.split( ';')[0]
117: # Some proxies seem to send invalid date strings for this
118: # header. If the date string is not valid, we ignore it
119: # rather than raise an error to be generally consistent
120: # with common servers such as Apache (which can usually
121: # understand the screwy date string as a lucky side effect
122: # of the way they parse it).
123: # This happens to be what RFC2616 tells us to do in the face of an
124: # invalid date.
125: try: mod_since=long(DateTime(header).timeTime())
126: except: mod_since=None
127: if mod_since is not None:
128: if self._p_mtime:
129: last_mod = long(self._p_mtime)
130: else:
131: last_mod = long(0)
132: if last_mod > 0 and last_mod <= mod_since:
133: # Set header values since apache caching will return Content-Length
134: # of 0 in response if size is not set here
135: RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime))
136: RESPONSE.setHeader('Content-Type', self.content_type)
137: RESPONSE.setHeader('Content-Length', self.size)
138: RESPONSE.setHeader('Accept-Ranges', 'bytes')
139: self.ZCacheable_set(None)
140: RESPONSE.setStatus(304)
141: return ''
142:
143: if self.precondition and hasattr(self,self.precondition):
144: # Grab whatever precondition was defined and then
145: # execute it. The precondition will raise an exception
146: # if something violates its terms.
147: c=getattr(self,self.precondition)
148: if hasattr(c,'isDocTemp') and c.isDocTemp:
149: c(REQUEST['PARENTS'][1],REQUEST)
150: else:
151: c()
152:
153: # HTTP Range header handling
154: range = REQUEST.get_header('Range', None)
155: request_range = REQUEST.get_header('Request-Range', None)
156: if request_range is not None:
157: # Netscape 2 through 4 and MSIE 3 implement a draft version
158: # Later on, we need to serve a different mime-type as well.
159: range = request_range
160: if_range = REQUEST.get_header('If-Range', None)
161: if range is not None:
162: ranges = HTTPRangeSupport.parseRange(range)
163:
164: if if_range is not None:
165: # Only send ranges if the data isn't modified, otherwise send
166: # the whole object. Support both ETags and Last-Modified dates!
167: if len(if_range) > 1 and if_range[:2] == 'ts':
168: # ETag:
169: if if_range != self.http__etag():
170: # Modified, so send a normal response. We delete
171: # the ranges, which causes us to skip to the 200
172: # response.
173: ranges = None
174: else:
175: # Date
176: date = if_range.split( ';')[0]
177: try: mod_since=long(DateTime(date).timeTime())
178: except: mod_since=None
179: if mod_since is not None:
180: if self._p_mtime:
181: last_mod = long(self._p_mtime)
182: else:
183: last_mod = long(0)
184: if last_mod > mod_since:
185: # Modified, so send a normal response. We delete
186: # the ranges, which causes us to skip to the 200
187: # response.
188: ranges = None
189:
190: if ranges:
191: # Search for satisfiable ranges.
192: satisfiable = 0
193: for start, end in ranges:
194: if start < self.size:
195: satisfiable = 1
196: break
197:
198: if not satisfiable:
199: RESPONSE.setHeader('Content-Range',
200: 'bytes */%d' % self.size)
201: RESPONSE.setHeader('Accept-Ranges', 'bytes')
202: RESPONSE.setHeader('Last-Modified',
203: rfc1123_date(self._p_mtime))
204: RESPONSE.setHeader('Content-Type', self.content_type)
205: RESPONSE.setHeader('Content-Length', self.size)
206: RESPONSE.setStatus(416)
207: return ''
208:
209: ranges = HTTPRangeSupport.expandRanges(ranges, self.size)
210:
211: if len(ranges) == 1:
212: # Easy case, set extra header and return partial set.
213: start, end = ranges[0]
214: size = end - start
215:
216: RESPONSE.setHeader('Last-Modified',
217: rfc1123_date(self._p_mtime))
218: RESPONSE.setHeader('Content-Type', self.content_type)
219: RESPONSE.setHeader('Content-Length', size)
220: RESPONSE.setHeader('Accept-Ranges', 'bytes')
221: RESPONSE.setHeader('Content-Range',
222: 'bytes %d-%d/%d' % (start, end - 1, self.size))
223: RESPONSE.setStatus(206) # Partial content
224:
225: data = urllib.urlopen(self.baseUrl+self.queryString).read()
226: if type(data) is StringType:
227: return data[start:end]
228:
229: # Linked Pdata objects. Urgh.
230: pos = 0
231: while data is not None:
232: l = len(data.data)
233: pos = pos + l
234: if pos > start:
235: # We are within the range
236: lstart = l - (pos - start)
237:
238: if lstart < 0: lstart = 0
239:
240: # find the endpoint
241: if end <= pos:
242: lend = l - (pos - end)
243:
244: # Send and end transmission
245: RESPONSE.write(data[lstart:lend])
246: break
247:
248: # Not yet at the end, transmit what we have.
249: RESPONSE.write(data[lstart:])
250:
251: data = data.next
252:
253: return ''
254:
255: else:
256: boundary = choose_boundary()
257:
258: # Calculate the content length
259: size = (8 + len(boundary) + # End marker length
260: len(ranges) * ( # Constant lenght per set
261: 49 + len(boundary) + len(self.content_type) +
262: len('%d' % self.size)))
263: for start, end in ranges:
264: # Variable length per set
265: size = (size + len('%d%d' % (start, end - 1)) +
266: end - start)
267:
268:
269: # Some clients implement an earlier draft of the spec, they
270: # will only accept x-byteranges.
271: draftprefix = (request_range is not None) and 'x-' or ''
272:
273: RESPONSE.setHeader('Content-Length', size)
274: RESPONSE.setHeader('Accept-Ranges', 'bytes')
275: RESPONSE.setHeader('Last-Modified',
276: rfc1123_date(self._p_mtime))
277: RESPONSE.setHeader('Content-Type',
278: 'multipart/%sbyteranges; boundary=%s' % (
279: draftprefix, boundary))
280: RESPONSE.setStatus(206) # Partial content
281:
282: data = urllib.urlopen(self.baseUrl+self.queryString).read()
283: # The Pdata map allows us to jump into the Pdata chain
284: # arbitrarily during out-of-order range searching.
285: pdata_map = {}
286: pdata_map[0] = data
287:
288: for start, end in ranges:
289: RESPONSE.write('\r\n--%s\r\n' % boundary)
290: RESPONSE.write('Content-Type: %s\r\n' %
291: self.content_type)
292: RESPONSE.write(
293: 'Content-Range: bytes %d-%d/%d\r\n\r\n' % (
294: start, end - 1, self.size))
295:
296: if type(data) is StringType:
297: RESPONSE.write(data[start:end])
298:
299: else:
300: # Yippee. Linked Pdata objects. The following
301: # calculations allow us to fast-forward through the
302: # Pdata chain without a lot of dereferencing if we
303: # did the work already.
304: first_size = len(pdata_map[0].data)
305: if start < first_size:
306: closest_pos = 0
307: else:
308: closest_pos = (
309: ((start - first_size) >> 16 << 16) +
310: first_size)
311: pos = min(closest_pos, max(pdata_map.keys()))
312: data = pdata_map[pos]
313:
314: while data is not None:
315: l = len(data.data)
316: pos = pos + l
317: if pos > start:
318: # We are within the range
319: lstart = l - (pos - start)
320:
321: if lstart < 0: lstart = 0
322:
323: # find the endpoint
324: if end <= pos:
325: lend = l - (pos - end)
326:
327: # Send and loop to next range
328: RESPONSE.write(data[lstart:lend])
329: break
330:
331: # Not yet at the end, transmit what we have.
332: RESPONSE.write(data[lstart:])
333:
334: data = data.next
335: # Store a reference to a Pdata chain link so we
336: # don't have to deref during this request again.
337: pdata_map[pos] = data
338:
339: # Do not keep the link references around.
340: del pdata_map
341:
342: RESPONSE.write('\r\n--%s--\r\n' % boundary)
343: return ''
344:
345: RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime))
346: RESPONSE.setHeader('Content-Type', self.content_type)
347: RESPONSE.setHeader('Content-Length', self.size)
348: RESPONSE.setHeader('Accept-Ranges', 'bytes')
349:
350: # Don't cache the data itself, but provide an opportunity
351: # for a cache manager to set response headers.
352: self.ZCacheable_set(None)
353:
354: data=urllib.urlopen(self.baseUrl+self.queryString).read()
355:
356: if type(data) is type(''):
357: RESPONSE.setBase(None)
358: return data
359:
360: while data is not None:
361: RESPONSE.write(data.data)
362: data=data.next
363:
364: return ''
365:
366:
367: def manage_addZogiImageForm(self):
368: """Form for adding"""
1.18 casties 369: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiImage.zpt')).__of__(self)
1.4 dwinter 370: return pt()
371:
372:
373: def manage_addZogiImage(self,id,title,baseUrl, queryString,RESPONSE=None):
374: """add dgilib"""
375: newObj=zogiImage(id,title,baseUrl, queryString)
376: self.Destination()._setObject(id,newObj)
377: if RESPONSE is not None:
378: RESPONSE.redirect('manage_main')
379:
380:
381:
1.1 dwinter 382: class zogiLib(Folder):
383: """StandardElement"""
384:
385: meta_type="zogiLib"
386:
1.18 casties 387: manage_options = Folder.manage_options+(
388: {'label':'Main Config','action':'changeZogiLibForm'},
389: )
1.1 dwinter 390:
1.27 casties 391: def __init__(self, id, title, digilibBaseUrl, localFileBase, version="book", basePath="", dlTarget=None):
1.1 dwinter 392: """init"""
393:
394: self.id=id
395: self.title=title
1.2 dwinter 396: self.digilibBaseUrl=digilibBaseUrl
1.1 dwinter 397: self.localFileBase=localFileBase
1.21 casties 398: self.basePath=basePath
1.18 casties 399: self.layout=version
1.27 casties 400: if dlTarget:
401: self.dlTarget = dlTarget
402: else:
403: self.dlTarget = "digilib"
1.1 dwinter 404:
1.28 casties 405: def version(self):
406: """version information"""
407: return ZOGIVERSION
408:
1.18 casties 409: def getDLInfo(self):
410: """get DLInfo from digilib server"""
411: paramH={}
412: baseUrl=re.sub("servlet/Scaler","dlInfo-xml.jsp",self.digilibBaseUrl)
413: try:
414: url=urllib.urlopen(baseUrl+self.REQUEST['QUERY_STRING'])
415: dom=xml.dom.minidom.parse(url)
416: params=dom.getElementsByTagName('parameter')
417: for param in params:
418: paramH[param.getAttribute('name')]=param.getAttribute('value')
419: return paramH
420: except:
421: return null
422:
1.1 dwinter 423:
1.18 casties 424: def createHeadJS(self):
1.19 casties 425: """generate all javascript tags for head"""
1.26 casties 426: self.checkQuery()
427: bt = self.REQUEST.SESSION['browserType']
428: if bt['staticHTML']:
429: return
430:
1.18 casties 431: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogilib_head_js')).__of__(self)
432: return pt()
1.19 casties 433:
434: def createParamJS(self):
435: """generate javascript for parameters only"""
1.26 casties 436: self.checkQuery()
437: bt = self.REQUEST.SESSION['browserType']
438: if bt['staticHTML']:
439: return
440:
1.19 casties 441: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogilib_param_js')).__of__(self)
442: return pt()
443:
1.3 dwinter 444:
1.26 casties 445: def createScalerImg(self, requestString=None, bottom=0, side=0, width=500, height=500):
1.18 casties 446: """generate Scaler IMG Tag"""
1.20 casties 447: self.checkQuery()
448: bt = self.REQUEST.SESSION['browserType']
1.24 casties 449: # override with parameters from session
450: if self.REQUEST.SESSION.has_key('scalerDiv'):
1.26 casties 451: (requestString, bottom, side, width, height) = self.REQUEST.SESSION['scalerDiv']
1.24 casties 452: # if not explicitly defined take normal request
1.18 casties 453: if not requestString:
1.21 casties 454: requestString = self.getAllDLParams()
1.18 casties 455: url = self.digilibBaseUrl+requestString
1.24 casties 456: # construct bottom and side insets
457: b_par = ""
458: s_par = ""
459: if (bottom != 0) or (side != 0):
460: b_par = "-" + str(int(bottom))
461: s_par = "-" + str(int(side))
1.18 casties 462: tag = ""
1.26 casties 463: if bt['staticHTML']:
464: tag += '<div id="scaler"><img id="pic" src="%s&dw=%i&dh=%i" /></div>'%(url, int(width-side), int(height-bottom))
1.18 casties 465: else:
1.26 casties 466: if bt['isN4']:
467: # N4 needs layers
468: tag += '<ilayer id="scaler">'
469: else:
470: tag += '<div id="scaler">'
471: tag += '<script type="text/javascript">'
472: tag += "var ps = bestPicSize(getElement('scaler'));"
473: # write img tag with javascript
474: tag += 'document.write(\'<img id="pic" src="%s&dw=\'+(ps.width%s)+\'&dh=\'+(ps.height%s)+\'" />\');'%(url, s_par, b_par)
475: tag += '</script>'
476: if bt['isN4']:
477: tag += '</ilayer>'
478: else:
479: tag += '</div>'
1.18 casties 480: return tag
1.1 dwinter 481:
1.26 casties 482: def createScalerDiv(self, requestString = None, bottom = 0, side = 0, width=500, height=500):
1.23 casties 483: """generate scaler img and table with navigation arrows"""
484: self.checkQuery()
1.24 casties 485: if requestString != None or bottom != 0 or side != 0:
1.26 casties 486: self.REQUEST.SESSION['scalerDiv'] = (requestString, bottom, side, width, height)
1.24 casties 487: else:
488: if self.REQUEST.SESSION.has_key('scalerDiv'):
1.26 casties 489: # make shure to remove unused parameter
1.24 casties 490: del self.REQUEST.SESSION['scalerDiv']
1.26 casties 491:
1.23 casties 492: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt/zogilib_img_div')).__of__(self)
493: return pt()
494:
1.18 casties 495: def createAuxDiv(self):
496: """generate other divs"""
1.20 casties 497: self.checkQuery()
498: bt = self.REQUEST.SESSION['browserType']
1.26 casties 499: if bt['staticHTML']:
500: return
501: if bt['isN4']:
1.18 casties 502: f = 'zpt/zogilib_divsN4.zpt'
503: else:
504: f = 'zpt/zogilib_divs.zpt'
505: pt=PageTemplateFile(os.path.join(package_home(globals()),f)).__of__(self)
506: return pt()
1.3 dwinter 507:
1.9 dwinter 508:
1.18 casties 509: def option_js(self):
1.28 casties 510: """javascript"""
511: return sendFile(self, 'js/option.js', 'text/plain')
1.1 dwinter 512:
1.18 casties 513: def dl_lib_js(self):
514: """javascript"""
515: return sendFile(self, 'js/dl_lib.js', 'text/plain')
516:
517: def js_lib_js(self):
518: """javascript"""
519: return sendFile(self, 'js/js_lib.js', 'text/plain')
1.1 dwinter 520:
1.18 casties 521: def optionwindow(self):
522: """showoptions"""
1.26 casties 523: self.checkQuery()
524: bt = self.REQUEST.SESSION['browserType']
525: if bt['staticHTML']:
526: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/optionwindow_static.zpt')).__of__(self)
527: else:
528: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/optionwindow.zpt')).__of__(self)
1.18 casties 529: return pt()
1.13 casties 530:
531: def mark1(self):
532: """mark image"""
1.18 casties 533: return sendFile(self, 'images/mark1.gif', 'image/gif')
1.13 casties 534:
535: def mark2(self):
536: """mark image"""
1.18 casties 537: return sendFile(self, 'images/mark2.gif', 'image/gif')
1.13 casties 538:
539: def mark3(self):
540: """mark image"""
1.18 casties 541: return sendFile(self, 'images/mark3.gif', 'image/gif')
1.13 casties 542:
543: def mark4(self):
544: """mark image"""
1.18 casties 545: return sendFile(self, 'images/mark4.gif', 'image/gif')
1.13 casties 546:
547: def mark5(self):
548: """mark image"""
1.18 casties 549: return sendFile(self, 'images/mark5.gif', 'image/gif')
1.13 casties 550:
551: def mark6(self):
552: """mark image"""
1.18 casties 553: return sendFile(self, 'images/mark6.gif', 'image/gif')
1.13 casties 554:
555: def mark7(self):
556: """mark image"""
1.18 casties 557: return sendFile(self, 'images/mark7.gif', 'image/gif')
1.13 casties 558:
559: def mark8(self):
560: """mark image"""
1.18 casties 561: return sendFile(self, 'images/mark8.gif', 'image/gif')
1.13 casties 562:
563: def corner1(self):
564: """mark image"""
1.18 casties 565: return sendFile(self, 'images/olinks.gif', 'image/gif')
1.13 casties 566:
567: def corner2(self):
568: """mark image"""
1.18 casties 569: return sendFile(self, 'images/orechts.gif', 'image/gif')
1.13 casties 570:
571: def corner3(self):
572: """mark image"""
1.18 casties 573: return sendFile(self, 'images/ulinks.gif', 'image/gif')
1.13 casties 574:
575: def corner4(self):
576: """mark image"""
1.18 casties 577: return sendFile(self, 'images/urechts.gif', 'image/gif')
1.13 casties 578:
1.22 casties 579: def up_img(self):
580: """mark image"""
581: return sendFile(self, 'images/up.gif', 'image/gif')
582:
583: def down_img(self):
584: """mark image"""
585: return sendFile(self, 'images/down.gif', 'image/gif')
586:
587: def left_img(self):
588: """mark image"""
589: return sendFile(self, 'images/left.gif', 'image/gif')
590:
591: def right_img(self):
592: """mark image"""
593: return sendFile(self, 'images/right.gif', 'image/gif')
1.13 casties 594:
595:
1.1 dwinter 596:
597: def index_html(self):
598: """main action"""
1.26 casties 599: self.checkQuery()
600: bt = self.REQUEST.SESSION['browserType']
1.18 casties 601: tp = "zogiLibMainTemplate"
602: if hasattr(self, tp):
603: pt = getattr(self, tp)
604: else:
1.26 casties 605: tpt = self.layout
606: if bt['staticHTML']:
607: tpt = "static"
608:
609: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogiLibMain_%s'%tpt)).__of__(self)
610:
1.18 casties 611: return pt()
612:
1.1 dwinter 613:
614:
1.21 casties 615: def storeQuery(self, more = None):
1.1 dwinter 616: """storeQuery in session"""
1.18 casties 617: dlParams = {}
1.1 dwinter 618: for fm in self.REQUEST.form.keys():
1.18 casties 619: dlParams[fm] = self.REQUEST.form[fm]
1.21 casties 620: # look for more
621: if more:
622: for fm in more.split('&'):
623: try:
624: pv = fm.split('=')
625: dlParams[pv[0]] = pv[1]
626: except:
1.26 casties 627: pass
628:
1.21 casties 629: # parse digilib mode parameter
1.18 casties 630: if 'mo' in dlParams:
631: if len(dlParams['mo']) > 0:
632: modes=dlParams['mo'].split(',')
633: else:
634: modes=[]
635:
636: self.REQUEST.SESSION['query'] = dlParams
637: self.REQUEST.SESSION['dlModes'] = modes
638: self.REQUEST.SESSION['dlInfo'] = self.getDLInfo()
1.26 casties 639: if not self.REQUEST.SESSION.has_key('browserType'):
640: self.REQUEST.SESSION['browserType'] = browserCheck(self)
641:
642: return
1.1 dwinter 643:
1.20 casties 644: def checkQuery(self):
645: """check if the query has been stored"""
1.26 casties 646: if not (self.REQUEST.SESSION and self.REQUEST.SESSION.has_key('query')) :
1.20 casties 647: print "ZOGILIB: have to store query!!"
1.26 casties 648: self.storeQuery()
1.24 casties 649: return
1.23 casties 650:
1.24 casties 651: def zogilibPath(self, otherbase=None):
1.23 casties 652: """returns an URL to the zogiLib instance"""
653: url = self.REQUEST['URL1']
1.24 casties 654: # should end with "/"
655: if len(url) > 0 and url[-1] != '/':
656: url += '/'
657: if type(otherbase) is str:
658: url += otherbase
659: else:
660: url += self.basePath
1.23 casties 661: # should end with "/"
662: if len(url) > 0 and url[-1] != '/':
663: url += '/'
664: return url
1.3 dwinter 665:
1.22 casties 666: def getDLParam(self, param):
1.18 casties 667: """returns parameter"""
1.3 dwinter 668: try:
669: return self.REQUEST.SESSION['query'][param]
670: except:
1.24 casties 671: return
1.3 dwinter 672:
1.18 casties 673: def setDLParam(self, param, value):
674: """sets parameter"""
675: self.REQUEST.SESSION['query'][param] = value
676: return
677:
678: def getAllDLParams(self):
679: """parameter string for digilib"""
680: dlParams = self.REQUEST.SESSION['query']
681: # save modes
682: modes = self.REQUEST.SESSION['dlModes']
683: dlParams['mo'] = string.join(modes, ',')
684: # assemble query string
685: ret = ""
686: for param in dlParams.keys():
1.29 casties 687: if dlParams[param] is None: continue
1.18 casties 688: val = str(dlParams[param])
689: if val != "":
690: ret += param + "=" + val + "&"
1.28 casties 691:
1.18 casties 692: # omit trailing "&"
693: return ret.rstrip('&')
694:
695:
696: def setDLParams(self,pn=None,ws=None,rot=None,brgt=None,cont=None):
697: """setze Parameter"""
698:
1.23 casties 699: self.setDLParam('brgt', brgt)
700: self.setDLParam('cont', cont)
701: self.setDLParam('ws', ws)
702: self.setDLParam('rot', rot)
1.18 casties 703:
704: if pn:
1.21 casties 705: # unmark
706: self.setDLParam('mk', None)
1.18 casties 707: self.setDLParam('pn', pn)
708:
709: return self.display()
710:
711:
712: def display(self):
713: """(re)display page"""
714: params = self.getAllDLParams()
1.21 casties 715: if self.basePath:
716: self.REQUEST.RESPONSE.redirect(self.REQUEST['URL2']+'?'+params)
717: else:
718: self.REQUEST.RESPONSE.redirect(self.REQUEST['URL1']+'?'+params)
1.18 casties 719:
1.26 casties 720:
1.30 ! casties 721: def getDLTarget(self):
! 722: """returns dlTarget"""
! 723: self.checkQuery()
! 724: s = self.dlTarget
! 725: # s = 'dl'
! 726: # if self.getDLParam('fn'):
! 727: # s += "_" + self.getDLParam('fn')
! 728: # if self.getDLParam('pn'):
! 729: # s += "_" + self.getDLParam('pn')
! 730: return s
! 731:
1.26 casties 732: def setStaticHTML(self, static=True):
733: """sets the preference to static HTML"""
734: self.checkQuery()
735: self.REQUEST.SESSION['browserType']['staticHTML'] = static
736: return
737:
738: def isStaticHTML(self):
739: """returns if the page is using static HTML only"""
740: self.checkQuery()
741: return self.REQUEST.SESSION['browserType']['staticHTML']
742:
1.18 casties 743: def getPT(self):
744: """pagenums"""
745: di = self.REQUEST.SESSION['dlInfo']
746: if di:
747: return int(di['pt'])
748: else:
749: return 1
750:
751: def getPN(self):
752: """Pagenum"""
753: pn = self.getDLParam('pn')
1.25 casties 754: try:
1.18 casties 755: return int(pn)
1.25 casties 756: except:
1.3 dwinter 757: return 1
758:
1.18 casties 759: def getBiggerWS(self):
1.3 dwinter 760: """ws+1"""
1.23 casties 761: ws = self.getDLParam('ws')
1.25 casties 762: try:
1.26 casties 763: return float(ws)+0.5
1.25 casties 764: except:
1.26 casties 765: return 1.5
1.3 dwinter 766:
1.18 casties 767: def getSmallerWS(self):
768: """ws-1"""
769: ws=self.getDLParam('ws')
1.25 casties 770: try:
1.26 casties 771: return max(float(ws)-0.5, 1)
1.25 casties 772: except:
1.3 dwinter 773: return 1
1.1 dwinter 774:
1.18 casties 775: def hasMode(self, mode):
776: """returns if mode is in the diglib mo parameter"""
777: return (mode in self.REQUEST.SESSION['dlModes'])
778:
779: def hasNextPage(self):
780: """returns if there is a next page"""
781: pn = self.getPN()
782: pt = self.getPT()
783: return (pn < pt)
784:
785: def hasPrevPage(self):
786: """returns if there is a previous page"""
787: pn = self.getPN()
788: return (pn > 1)
1.1 dwinter 789:
1.22 casties 790: def canMoveLeft(self):
791: """returns if its possible to move left"""
792: wx = float(self.getDLParam('wx') or 0)
793: return (wx > 0)
794:
795: def canMoveRight(self):
796: """returns if its possible to move right"""
797: wx = float(self.getDLParam('wx') or 0)
798: ww = float(self.getDLParam('ww') or 1)
799: return (wx + ww < 1)
800:
801: def canMoveUp(self):
802: """returns if its possible to move up"""
803: wy = float(self.getDLParam('wy') or 0)
804: return (wy > 0)
805:
806: def canMoveDown(self):
807: """returns if its possible to move down"""
808: wy = float(self.getDLParam('wy') or 0)
809: wh = float(self.getDLParam('wh') or 1)
810: return (wy + wh < 1)
811:
1.26 casties 812:
813: def dl_StaticHTML(self):
814: """set rendering to static HTML"""
815: self.checkQuery()
816: self.REQUEST.SESSION['browserType']['staticHTML'] = True
817: return self.display()
818:
819: def dl_DynamicHTML(self):
820: """set rendering to dynamic HTML"""
821: self.checkQuery()
822: self.REQUEST.SESSION['browserType']['staticHTML'] = False
823: return self.display()
1.1 dwinter 824:
1.18 casties 825: def dl_HMirror(self):
826: """mirror action"""
827: modes = self.REQUEST.SESSION['dlModes']
828: if 'hmir' in modes:
829: modes.remove('hmir')
830: else:
831: modes.append('hmir')
1.1 dwinter 832:
1.18 casties 833: return self.display()
834:
835: def dl_VMirror(self):
836: """mirror action"""
837: modes = self.REQUEST.SESSION['dlModes']
838: if 'vmir' in modes:
839: modes.remove('vmir')
840: else:
841: modes.append('vmir')
1.1 dwinter 842:
1.18 casties 843: return self.display()
1.1 dwinter 844:
1.22 casties 845: def dl_Zoom(self, z):
846: """general zoom action"""
847: ww1 = float(self.getDLParam('ww') or 1)
848: wh1 = float(self.getDLParam('wh') or 1)
849: wx = float(self.getDLParam('wx') or 0)
850: wy = float(self.getDLParam('wy') or 0)
851: ww2 = ww1 * z
852: wh2 = wh1 * z
853: wx += (ww1 - ww2) / 2
854: wy += (wh1 - wh2) / 2
855: ww2 = max(min(ww2, 1), 0)
856: wh2 = max(min(wh2, 1), 0)
857: wx = max(min(wx, 1), 0)
858: wy = max(min(wy, 1), 0)
1.30 ! casties 859: self.setDLParam('ww', cropf(ww2))
! 860: self.setDLParam('wh', cropf(wh2))
! 861: self.setDLParam('wx', cropf(wx))
! 862: self.setDLParam('wy', cropf(wy))
1.22 casties 863: return self.display()
864:
865: def dl_ZoomIn(self):
866: """zoom in action"""
867: z = 0.7071
868: return self.dl_Zoom(z)
869:
870: def dl_ZoomOut(self):
871: """zoom out action"""
872: z = 1.4142
873: return self.dl_Zoom(z)
874:
875: def dl_Move(self, dx, dy):
876: """general move action"""
877: ww = float(self.getDLParam('ww') or 1)
878: wh = float(self.getDLParam('wh') or 1)
879: wx = float(self.getDLParam('wx') or 0)
880: wy = float(self.getDLParam('wy') or 0)
881: wx += dx * 0.5 * ww
882: wy += dy * 0.5 * wh
883: wx = max(min(wx, 1), 0)
884: wy = max(min(wy, 1), 0)
1.30 ! casties 885: self.setDLParam('wx', cropf(wx))
! 886: self.setDLParam('wy', cropf(wy))
1.22 casties 887: return self.display()
888:
889: def dl_MoveLeft(self):
890: """move left action"""
891: return self.dl_Move(-1, 0)
892:
893: def dl_MoveRight(self):
894: """move left action"""
895: return self.dl_Move(1, 0)
896:
897: def dl_MoveUp(self):
898: """move left action"""
899: return self.dl_Move(0, -1)
900:
901: def dl_MoveDown(self):
902: """move left action"""
903: return self.dl_Move(0, 1)
904:
1.18 casties 905: def dl_WholePage(self):
906: """zoom out action"""
907: self.setDLParam('ww', 1)
908: self.setDLParam('wh', 1)
909: self.setDLParam('wx', 0)
910: self.setDLParam('wy', 0)
911: return self.display()
912:
913: def dl_PrevPage(self):
914: """next page action"""
915: pn = self.getPN() - 1
916: if pn < 1:
917: pn = 1
918: self.setDLParam('pn', pn)
919: # unmark
920: self.setDLParam('mk', None)
921: return self.display()
922:
923: def dl_NextPage(self):
924: """next page action"""
925: pn = self.getPN() + 1
926: pt = self.getPT()
927: if pn > pt:
928: pn = pt
929: self.setDLParam('pn', pn)
930: # unmark
931: self.setDLParam('mk', None)
932: return self.display()
933:
934: def dl_FirstPage(self):
935: """first page action"""
936: self.setDLParam('pn', 1)
937: # unmark
938: self.setDLParam('mk', None)
939: return self.display()
940:
941: def dl_LastPage(self):
942: """last page action"""
943: self.setDLParam('pn', self.getPT())
944: # unmark
945: self.setDLParam('mk', None)
946: return self.display()
947:
948: def dl_Unmark(self):
949: """action to remove last mark"""
950: mk = self.getDLParam('mk')
951: if mk:
952: marks = mk.split(',')
953: marks.pop()
954: mk = string.join(marks, ',')
955: self.setDLParam('mk', mk)
956: return self.display()
1.1 dwinter 957:
958:
959:
1.18 casties 960: def changeZogiLibForm(self):
961: """Main configuration"""
962: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/changeZogiLibForm.zpt')).__of__(self)
963: return pt()
1.1 dwinter 964:
1.27 casties 965: def changeZogiLib(self,title,digilibBaseUrl, localFileBase, version, basePath, dlTarget, RESPONSE=None):
1.18 casties 966: """change it"""
967: self.title=title
968: self.digilibBaseUrl=digilibBaseUrl
969: self.localFileBase=localFileBase
1.21 casties 970: self.basePath = basePath
1.18 casties 971: self.layout=version
1.27 casties 972: if dlTarget:
973: self.dlTarget = dlTarget
974: else:
975: self.dlTarget = "digilib"
1.3 dwinter 976:
1.18 casties 977: if RESPONSE is not None:
978: RESPONSE.redirect('manage_main')
1.8 dwinter 979:
980:
1.1 dwinter 981: def manage_addZogiLibForm(self):
982: """interface for adding zogilib"""
1.18 casties 983: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiLibForm')).__of__(self)
1.1 dwinter 984: return pt()
985:
1.27 casties 986: def manage_addZogiLib(self,id,title,digilibBaseUrl, localFileBase,version="book",basePath="",dlTarget="digilib",RESPONSE=None):
1.1 dwinter 987: """add dgilib"""
1.27 casties 988: newObj=zogiLib(id,title,digilibBaseUrl, localFileBase, version, basePath, dlTarget)
1.1 dwinter 989: self.Destination()._setObject(id,newObj)
990: if RESPONSE is not None:
991: RESPONSE.redirect('manage_main')
1.29 casties 992:
993:
994: class zogiLibPageTemplate(ZopePageTemplate):
995: """pageTemplate Objekt"""
996: meta_type="zogiLib_pageTemplate"
997:
998:
999: ## def __init__(self, id, text=None, contentType=None):
1000: ## self.id = str(id)
1001: ## self.ZBindings_edit(self._default_bindings)
1002: ## if text is None:
1003: ## text = open(self._default_cont).read()
1004: ## self.pt_edit(text, contentType)
1005:
1006: def manage_addZogiLibPageTemplateForm(self):
1007: """Form for adding"""
1008: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiLibPageTemplateForm')).__of__(self)
1009: return pt()
1010:
1011: def manage_addZogiLibPageTemplate(self, id='zogiLibMainTemplate', title=None, layout=None, text=None,
1012: REQUEST=None, submit=None):
1013: "Add a Page Template with optional file content."
1014:
1015: id = str(id)
1016: self._setObject(id, zogiLibPageTemplate(id))
1017: ob = getattr(self, id)
1018: if not layout: layout = "book"
1019: ob.pt_edit(open(os.path.join(package_home(globals()),'zpt/zogiLibMain_%s.zpt'%layout)).read(),None)
1020: if title:
1021: ob.pt_setTitle(title)
1022: try:
1023: u = self.DestinationURL()
1024: except AttributeError:
1025: u = REQUEST['URL1']
1026:
1027: u = "%s/%s" % (u, urllib.quote(id))
1028: REQUEST.RESPONSE.redirect(u+'/manage_main')
1029: return ''
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>