Annotation of zogiLib/zogiLib.py, revision 1.31
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:
1.31 ! dwinter 528: finds=self.ZopeFind(self,obj_ids=['viewingTools.zpt'])
! 529: if finds:
! 530:
! 531: return finds[0][1]()
! 532: else:
! 533: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/optionwindow.zpt')).__of__(self)
! 534: return pt()
1.13 casties 535:
536: def mark1(self):
537: """mark image"""
1.18 casties 538: return sendFile(self, 'images/mark1.gif', 'image/gif')
1.13 casties 539:
540: def mark2(self):
541: """mark image"""
1.18 casties 542: return sendFile(self, 'images/mark2.gif', 'image/gif')
1.13 casties 543:
544: def mark3(self):
545: """mark image"""
1.18 casties 546: return sendFile(self, 'images/mark3.gif', 'image/gif')
1.13 casties 547:
548: def mark4(self):
549: """mark image"""
1.18 casties 550: return sendFile(self, 'images/mark4.gif', 'image/gif')
1.13 casties 551:
552: def mark5(self):
553: """mark image"""
1.18 casties 554: return sendFile(self, 'images/mark5.gif', 'image/gif')
1.13 casties 555:
556: def mark6(self):
557: """mark image"""
1.18 casties 558: return sendFile(self, 'images/mark6.gif', 'image/gif')
1.13 casties 559:
560: def mark7(self):
561: """mark image"""
1.18 casties 562: return sendFile(self, 'images/mark7.gif', 'image/gif')
1.13 casties 563:
564: def mark8(self):
565: """mark image"""
1.18 casties 566: return sendFile(self, 'images/mark8.gif', 'image/gif')
1.13 casties 567:
568: def corner1(self):
569: """mark image"""
1.18 casties 570: return sendFile(self, 'images/olinks.gif', 'image/gif')
1.13 casties 571:
572: def corner2(self):
573: """mark image"""
1.18 casties 574: return sendFile(self, 'images/orechts.gif', 'image/gif')
1.13 casties 575:
576: def corner3(self):
577: """mark image"""
1.18 casties 578: return sendFile(self, 'images/ulinks.gif', 'image/gif')
1.13 casties 579:
580: def corner4(self):
581: """mark image"""
1.18 casties 582: return sendFile(self, 'images/urechts.gif', 'image/gif')
1.13 casties 583:
1.22 casties 584: def up_img(self):
585: """mark image"""
586: return sendFile(self, 'images/up.gif', 'image/gif')
587:
588: def down_img(self):
589: """mark image"""
590: return sendFile(self, 'images/down.gif', 'image/gif')
591:
592: def left_img(self):
593: """mark image"""
594: return sendFile(self, 'images/left.gif', 'image/gif')
595:
596: def right_img(self):
597: """mark image"""
598: return sendFile(self, 'images/right.gif', 'image/gif')
1.13 casties 599:
600:
1.1 dwinter 601:
602: def index_html(self):
603: """main action"""
1.26 casties 604: self.checkQuery()
605: bt = self.REQUEST.SESSION['browserType']
1.18 casties 606: tp = "zogiLibMainTemplate"
607: if hasattr(self, tp):
608: pt = getattr(self, tp)
609: else:
1.26 casties 610: tpt = self.layout
611: if bt['staticHTML']:
612: tpt = "static"
613:
614: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogiLibMain_%s'%tpt)).__of__(self)
615:
1.18 casties 616: return pt()
617:
1.1 dwinter 618:
619:
1.21 casties 620: def storeQuery(self, more = None):
1.1 dwinter 621: """storeQuery in session"""
1.18 casties 622: dlParams = {}
1.1 dwinter 623: for fm in self.REQUEST.form.keys():
1.18 casties 624: dlParams[fm] = self.REQUEST.form[fm]
1.21 casties 625: # look for more
626: if more:
627: for fm in more.split('&'):
628: try:
629: pv = fm.split('=')
630: dlParams[pv[0]] = pv[1]
631: except:
1.26 casties 632: pass
633:
1.21 casties 634: # parse digilib mode parameter
1.18 casties 635: if 'mo' in dlParams:
636: if len(dlParams['mo']) > 0:
637: modes=dlParams['mo'].split(',')
638: else:
639: modes=[]
640:
641: self.REQUEST.SESSION['query'] = dlParams
642: self.REQUEST.SESSION['dlModes'] = modes
643: self.REQUEST.SESSION['dlInfo'] = self.getDLInfo()
1.26 casties 644: if not self.REQUEST.SESSION.has_key('browserType'):
645: self.REQUEST.SESSION['browserType'] = browserCheck(self)
646:
647: return
1.1 dwinter 648:
1.20 casties 649: def checkQuery(self):
650: """check if the query has been stored"""
1.26 casties 651: if not (self.REQUEST.SESSION and self.REQUEST.SESSION.has_key('query')) :
1.20 casties 652: print "ZOGILIB: have to store query!!"
1.26 casties 653: self.storeQuery()
1.24 casties 654: return
1.23 casties 655:
1.24 casties 656: def zogilibPath(self, otherbase=None):
1.23 casties 657: """returns an URL to the zogiLib instance"""
658: url = self.REQUEST['URL1']
1.24 casties 659: # should end with "/"
660: if len(url) > 0 and url[-1] != '/':
661: url += '/'
662: if type(otherbase) is str:
663: url += otherbase
664: else:
665: url += self.basePath
1.23 casties 666: # should end with "/"
667: if len(url) > 0 and url[-1] != '/':
668: url += '/'
669: return url
1.3 dwinter 670:
1.22 casties 671: def getDLParam(self, param):
1.18 casties 672: """returns parameter"""
1.3 dwinter 673: try:
674: return self.REQUEST.SESSION['query'][param]
675: except:
1.24 casties 676: return
1.3 dwinter 677:
1.18 casties 678: def setDLParam(self, param, value):
679: """sets parameter"""
680: self.REQUEST.SESSION['query'][param] = value
681: return
682:
683: def getAllDLParams(self):
684: """parameter string for digilib"""
685: dlParams = self.REQUEST.SESSION['query']
686: # save modes
687: modes = self.REQUEST.SESSION['dlModes']
688: dlParams['mo'] = string.join(modes, ',')
689: # assemble query string
690: ret = ""
691: for param in dlParams.keys():
1.29 casties 692: if dlParams[param] is None: continue
1.18 casties 693: val = str(dlParams[param])
694: if val != "":
695: ret += param + "=" + val + "&"
1.28 casties 696:
1.18 casties 697: # omit trailing "&"
698: return ret.rstrip('&')
699:
700:
701: def setDLParams(self,pn=None,ws=None,rot=None,brgt=None,cont=None):
702: """setze Parameter"""
703:
1.23 casties 704: self.setDLParam('brgt', brgt)
705: self.setDLParam('cont', cont)
706: self.setDLParam('ws', ws)
707: self.setDLParam('rot', rot)
1.18 casties 708:
709: if pn:
1.21 casties 710: # unmark
711: self.setDLParam('mk', None)
1.18 casties 712: self.setDLParam('pn', pn)
713:
714: return self.display()
715:
716:
717: def display(self):
718: """(re)display page"""
719: params = self.getAllDLParams()
1.21 casties 720: if self.basePath:
721: self.REQUEST.RESPONSE.redirect(self.REQUEST['URL2']+'?'+params)
722: else:
723: self.REQUEST.RESPONSE.redirect(self.REQUEST['URL1']+'?'+params)
1.18 casties 724:
1.26 casties 725:
1.30 casties 726: def getDLTarget(self):
727: """returns dlTarget"""
728: self.checkQuery()
729: s = self.dlTarget
730: # s = 'dl'
731: # if self.getDLParam('fn'):
732: # s += "_" + self.getDLParam('fn')
733: # if self.getDLParam('pn'):
734: # s += "_" + self.getDLParam('pn')
735: return s
736:
1.26 casties 737: def setStaticHTML(self, static=True):
738: """sets the preference to static HTML"""
739: self.checkQuery()
740: self.REQUEST.SESSION['browserType']['staticHTML'] = static
741: return
742:
743: def isStaticHTML(self):
744: """returns if the page is using static HTML only"""
745: self.checkQuery()
746: return self.REQUEST.SESSION['browserType']['staticHTML']
747:
1.18 casties 748: def getPT(self):
749: """pagenums"""
750: di = self.REQUEST.SESSION['dlInfo']
751: if di:
752: return int(di['pt'])
753: else:
754: return 1
755:
756: def getPN(self):
757: """Pagenum"""
758: pn = self.getDLParam('pn')
1.25 casties 759: try:
1.18 casties 760: return int(pn)
1.25 casties 761: except:
1.3 dwinter 762: return 1
763:
1.18 casties 764: def getBiggerWS(self):
1.3 dwinter 765: """ws+1"""
1.23 casties 766: ws = self.getDLParam('ws')
1.25 casties 767: try:
1.26 casties 768: return float(ws)+0.5
1.25 casties 769: except:
1.26 casties 770: return 1.5
1.3 dwinter 771:
1.18 casties 772: def getSmallerWS(self):
773: """ws-1"""
774: ws=self.getDLParam('ws')
1.25 casties 775: try:
1.26 casties 776: return max(float(ws)-0.5, 1)
1.25 casties 777: except:
1.3 dwinter 778: return 1
1.1 dwinter 779:
1.18 casties 780: def hasMode(self, mode):
781: """returns if mode is in the diglib mo parameter"""
782: return (mode in self.REQUEST.SESSION['dlModes'])
783:
784: def hasNextPage(self):
785: """returns if there is a next page"""
786: pn = self.getPN()
787: pt = self.getPT()
788: return (pn < pt)
789:
790: def hasPrevPage(self):
791: """returns if there is a previous page"""
792: pn = self.getPN()
793: return (pn > 1)
1.1 dwinter 794:
1.22 casties 795: def canMoveLeft(self):
796: """returns if its possible to move left"""
797: wx = float(self.getDLParam('wx') or 0)
798: return (wx > 0)
799:
800: def canMoveRight(self):
801: """returns if its possible to move right"""
802: wx = float(self.getDLParam('wx') or 0)
803: ww = float(self.getDLParam('ww') or 1)
804: return (wx + ww < 1)
805:
806: def canMoveUp(self):
807: """returns if its possible to move up"""
808: wy = float(self.getDLParam('wy') or 0)
809: return (wy > 0)
810:
811: def canMoveDown(self):
812: """returns if its possible to move down"""
813: wy = float(self.getDLParam('wy') or 0)
814: wh = float(self.getDLParam('wh') or 1)
815: return (wy + wh < 1)
816:
1.26 casties 817:
818: def dl_StaticHTML(self):
819: """set rendering to static HTML"""
820: self.checkQuery()
821: self.REQUEST.SESSION['browserType']['staticHTML'] = True
822: return self.display()
823:
824: def dl_DynamicHTML(self):
825: """set rendering to dynamic HTML"""
826: self.checkQuery()
827: self.REQUEST.SESSION['browserType']['staticHTML'] = False
828: return self.display()
1.1 dwinter 829:
1.18 casties 830: def dl_HMirror(self):
831: """mirror action"""
832: modes = self.REQUEST.SESSION['dlModes']
833: if 'hmir' in modes:
834: modes.remove('hmir')
835: else:
836: modes.append('hmir')
1.1 dwinter 837:
1.18 casties 838: return self.display()
839:
840: def dl_VMirror(self):
841: """mirror action"""
842: modes = self.REQUEST.SESSION['dlModes']
843: if 'vmir' in modes:
844: modes.remove('vmir')
845: else:
846: modes.append('vmir')
1.1 dwinter 847:
1.18 casties 848: return self.display()
1.1 dwinter 849:
1.22 casties 850: def dl_Zoom(self, z):
851: """general zoom action"""
852: ww1 = float(self.getDLParam('ww') or 1)
853: wh1 = float(self.getDLParam('wh') or 1)
854: wx = float(self.getDLParam('wx') or 0)
855: wy = float(self.getDLParam('wy') or 0)
856: ww2 = ww1 * z
857: wh2 = wh1 * z
858: wx += (ww1 - ww2) / 2
859: wy += (wh1 - wh2) / 2
860: ww2 = max(min(ww2, 1), 0)
861: wh2 = max(min(wh2, 1), 0)
862: wx = max(min(wx, 1), 0)
863: wy = max(min(wy, 1), 0)
1.30 casties 864: self.setDLParam('ww', cropf(ww2))
865: self.setDLParam('wh', cropf(wh2))
866: self.setDLParam('wx', cropf(wx))
867: self.setDLParam('wy', cropf(wy))
1.22 casties 868: return self.display()
869:
870: def dl_ZoomIn(self):
871: """zoom in action"""
872: z = 0.7071
873: return self.dl_Zoom(z)
874:
875: def dl_ZoomOut(self):
876: """zoom out action"""
877: z = 1.4142
878: return self.dl_Zoom(z)
879:
880: def dl_Move(self, dx, dy):
881: """general move action"""
882: ww = float(self.getDLParam('ww') or 1)
883: wh = float(self.getDLParam('wh') or 1)
884: wx = float(self.getDLParam('wx') or 0)
885: wy = float(self.getDLParam('wy') or 0)
886: wx += dx * 0.5 * ww
887: wy += dy * 0.5 * wh
888: wx = max(min(wx, 1), 0)
889: wy = max(min(wy, 1), 0)
1.30 casties 890: self.setDLParam('wx', cropf(wx))
891: self.setDLParam('wy', cropf(wy))
1.22 casties 892: return self.display()
893:
894: def dl_MoveLeft(self):
895: """move left action"""
896: return self.dl_Move(-1, 0)
897:
898: def dl_MoveRight(self):
899: """move left action"""
900: return self.dl_Move(1, 0)
901:
902: def dl_MoveUp(self):
903: """move left action"""
904: return self.dl_Move(0, -1)
905:
906: def dl_MoveDown(self):
907: """move left action"""
908: return self.dl_Move(0, 1)
909:
1.18 casties 910: def dl_WholePage(self):
911: """zoom out action"""
912: self.setDLParam('ww', 1)
913: self.setDLParam('wh', 1)
914: self.setDLParam('wx', 0)
915: self.setDLParam('wy', 0)
916: return self.display()
917:
918: def dl_PrevPage(self):
919: """next page action"""
920: pn = self.getPN() - 1
921: if pn < 1:
922: pn = 1
923: self.setDLParam('pn', pn)
924: # unmark
925: self.setDLParam('mk', None)
926: return self.display()
927:
928: def dl_NextPage(self):
929: """next page action"""
930: pn = self.getPN() + 1
931: pt = self.getPT()
932: if pn > pt:
933: pn = pt
934: self.setDLParam('pn', pn)
935: # unmark
936: self.setDLParam('mk', None)
937: return self.display()
938:
939: def dl_FirstPage(self):
940: """first page action"""
941: self.setDLParam('pn', 1)
942: # unmark
943: self.setDLParam('mk', None)
944: return self.display()
945:
946: def dl_LastPage(self):
947: """last page action"""
948: self.setDLParam('pn', self.getPT())
949: # unmark
950: self.setDLParam('mk', None)
951: return self.display()
952:
953: def dl_Unmark(self):
954: """action to remove last mark"""
955: mk = self.getDLParam('mk')
956: if mk:
957: marks = mk.split(',')
958: marks.pop()
959: mk = string.join(marks, ',')
960: self.setDLParam('mk', mk)
961: return self.display()
1.1 dwinter 962:
963:
964:
1.18 casties 965: def changeZogiLibForm(self):
966: """Main configuration"""
967: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/changeZogiLibForm.zpt')).__of__(self)
968: return pt()
1.1 dwinter 969:
1.27 casties 970: def changeZogiLib(self,title,digilibBaseUrl, localFileBase, version, basePath, dlTarget, RESPONSE=None):
1.18 casties 971: """change it"""
972: self.title=title
973: self.digilibBaseUrl=digilibBaseUrl
974: self.localFileBase=localFileBase
1.21 casties 975: self.basePath = basePath
1.18 casties 976: self.layout=version
1.27 casties 977: if dlTarget:
978: self.dlTarget = dlTarget
979: else:
980: self.dlTarget = "digilib"
1.3 dwinter 981:
1.18 casties 982: if RESPONSE is not None:
983: RESPONSE.redirect('manage_main')
1.8 dwinter 984:
985:
1.1 dwinter 986: def manage_addZogiLibForm(self):
987: """interface for adding zogilib"""
1.18 casties 988: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiLibForm')).__of__(self)
1.1 dwinter 989: return pt()
990:
1.27 casties 991: def manage_addZogiLib(self,id,title,digilibBaseUrl, localFileBase,version="book",basePath="",dlTarget="digilib",RESPONSE=None):
1.1 dwinter 992: """add dgilib"""
1.27 casties 993: newObj=zogiLib(id,title,digilibBaseUrl, localFileBase, version, basePath, dlTarget)
1.1 dwinter 994: self.Destination()._setObject(id,newObj)
995: if RESPONSE is not None:
996: RESPONSE.redirect('manage_main')
1.29 casties 997:
998:
999: class zogiLibPageTemplate(ZopePageTemplate):
1000: """pageTemplate Objekt"""
1001: meta_type="zogiLib_pageTemplate"
1002:
1003:
1004: ## def __init__(self, id, text=None, contentType=None):
1005: ## self.id = str(id)
1006: ## self.ZBindings_edit(self._default_bindings)
1007: ## if text is None:
1008: ## text = open(self._default_cont).read()
1009: ## self.pt_edit(text, contentType)
1010:
1011: def manage_addZogiLibPageTemplateForm(self):
1012: """Form for adding"""
1013: pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiLibPageTemplateForm')).__of__(self)
1014: return pt()
1015:
1016: def manage_addZogiLibPageTemplate(self, id='zogiLibMainTemplate', title=None, layout=None, text=None,
1017: REQUEST=None, submit=None):
1018: "Add a Page Template with optional file content."
1019:
1020: id = str(id)
1021: self._setObject(id, zogiLibPageTemplate(id))
1022: ob = getattr(self, id)
1023: if not layout: layout = "book"
1024: ob.pt_edit(open(os.path.join(package_home(globals()),'zpt/zogiLibMain_%s.zpt'%layout)).read(),None)
1025: if title:
1026: ob.pt_setTitle(title)
1027: try:
1028: u = self.DestinationURL()
1029: except AttributeError:
1030: u = REQUEST['URL1']
1031:
1032: u = "%s/%s" % (u, urllib.quote(id))
1033: REQUEST.RESPONSE.redirect(u+'/manage_main')
1034: return ''
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>