File:  [Repository] / zogiLib / zogiLib.py
Revision 1.26: download - view: text, annotated - select for diffs - revision graph
Mon Jun 7 17:56:55 2004 UTC (20 years, 1 month ago) by casties
Branches: MAIN
CVS tags: HEAD
new also with static html version (not enabled by default)

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>