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