File:  [Repository] / zogiLib / zogiLib.py
Revision 1.21: download - view: text, annotated - select for diffs - revision graph
Wed Jun 2 21:53:15 2004 UTC (19 years, 11 months ago) by casties
Branches: MAIN
CVS tags: HEAD
finally working with vlp!


from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.PageTemplates.PageTemplate import PageTemplate
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
from OFS.Image import Image
from webdav.common import rfc1123_date

import xml.dom.minidom
from OFS.Folder import Folder
from xml_helpers import getText
import os
import re
import string
import urllib
from Globals import package_home

def getString(self,key,default=''):
    try:
        return self.REQUEST[key]
    except:
        return default

def sendFile(self, filename, type):
    """sends an object or a local file (in the product) as response"""
    paths = filename.split('/')
    object = self
    # look for an object called filename
    for path in paths:
        if hasattr(object, path):
	    object = getattr(object, path)
	else:
	    object = None
	    break
    if object:
	# if the object exists then send it
	return object.index_html(self.REQUEST.REQUEST, self.REQUEST.RESPONSE)
    else:
	# send a local file with the given content-type
	fn = os.path.join(package_home(globals()), filename)
	self.REQUEST.RESPONSE.setHeader("Content-Type", type)
	self.REQUEST.RESPONSE.write(file(fn).read())
    return

class BrowserCheck:
    """check the browsers request to find out the browser type"""
    
    def __init__(self, zope):
	self.ua = zope.REQUEST.get_header("HTTP_USER_AGENT")
	self.isIE = string.find(self.ua, 'MSIE') > -1
	self.isN4 = (string.find(self.ua, 'Mozilla/4.') > -1) and not self.isIE
	self.nav = self.ua[string.find(self.ua, '('):]
	ie = string.split(self.nav, "; ")[1]
	if string.find(ie, "MSIE") > -1:
	    self.versIE = string.split(ie, " ")[1]
	self.isMac = string.find(self.ua, 'Macintosh') > -1
	self.isWin = string.find(self.ua, 'Windows') > -1
	self.isIEWin = self.isIE and self.isWin
	self.isIEMac = self.isIE and self.isMac


def manage_addZogiLibMainTemplateForm(self):
    """Form for adding"""
    #FIXME:???
    pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/AddOSAS_thumbTemplate.zpt')).__of__(self)
    return pt()




def manage_addZogiLibMainTemplate(self, id,title=None, text=None,
                           REQUEST=None, submit=None):
    "Add a Page Template with optional file content."
    #FIXME:???
    id = str(id)
    if REQUEST is None:
        self._setObject(id, zogiLib_mainTemplate(id, text))
        ob = getattr(self, id)
       
        if title:
            ob.pt_setTitle(title)
        return ob
    else:
        file = REQUEST.form.get('file')
        headers = getattr(file, 'headers', None)
        if headers is None or not file.filename:
            zpt = zogiLib_mainTemplate(id)
        else:
            zpt = zogiLib_mainTemplate(id, file, headers.get('content_type'))

        self._setObject(id, zpt)
        ob = getattr(self, id)


        try:
            u = self.DestinationURL()
        except AttributeError:
            u = REQUEST['URL1']

        if submit == " Add and Edit ":
            u = "%s/%s" % (u, quote(id))
        REQUEST.RESPONSE.redirect(u+'/manage_main')
    return ''

    
class zogiImage(Image):
    """einzelnes Image"""
    meta_type="zogiImage"

    manage_options=ZopePageTemplate.manage_options+(
        {'label':'Main config','action':'changeZogiImageForm'},
       )
    
    
    def __init__(self,id,title,baseUrl,queryString,content_type='',precondition=''):
        """init"""
        self.id=id
        self.title=title
        self.baseUrl=baseUrl
        self.queryString=queryString
        self.content_type=content_type
        self.precondition=precondition

    def getData(self):
        """getUrlData"""
        return urllib.urlopen(self.baseUrl+self.queryString)

    def changeZogiImageForm(self):
        """Main configuration"""
        pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/changeZogiImageForm.zpt')).__of__(self)
        return pt()
    
    def changeZogiImage(self,title,baseUrl, queryString,RESPONSE=None):
        """change it"""
        self.title=title
        self.baseUrl=baseUrl
        self.queryString=queryString

        if RESPONSE is not None:
            RESPONSE.redirect('manage_main')

        
    def index_html(self, REQUEST, RESPONSE):
        """
        Modified version of OFS/Image.py
        
        The default view of the contents of a File or Image.

        Returns the contents of the file or image.  Also, sets the
        Content-Type HTTP header to the objects content type.
        """

        # HTTP If-Modified-Since header handling.
        header=REQUEST.get_header('If-Modified-Since', None)
        if header is not None:
            header=header.split( ';')[0]
            # Some proxies seem to send invalid date strings for this
            # header. If the date string is not valid, we ignore it
            # rather than raise an error to be generally consistent
            # with common servers such as Apache (which can usually
            # understand the screwy date string as a lucky side effect
            # of the way they parse it).
            # This happens to be what RFC2616 tells us to do in the face of an
            # invalid date.
            try:    mod_since=long(DateTime(header).timeTime())
            except: mod_since=None
            if mod_since is not None:
                if self._p_mtime:
                    last_mod = long(self._p_mtime)
                else:
                    last_mod = long(0)
                if last_mod > 0 and last_mod <= mod_since:
                    # Set header values since apache caching will return Content-Length
                    # of 0 in response if size is not set here
                    RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime))
                    RESPONSE.setHeader('Content-Type', self.content_type)
                    RESPONSE.setHeader('Content-Length', self.size)
                    RESPONSE.setHeader('Accept-Ranges', 'bytes')
                    self.ZCacheable_set(None)
                    RESPONSE.setStatus(304)
                    return ''

        if self.precondition and hasattr(self,self.precondition):
            # Grab whatever precondition was defined and then
            # execute it.  The precondition will raise an exception
            # if something violates its terms.
            c=getattr(self,self.precondition)
            if hasattr(c,'isDocTemp') and c.isDocTemp:
                c(REQUEST['PARENTS'][1],REQUEST)
            else:
                c()

        # HTTP Range header handling
        range = REQUEST.get_header('Range', None)
        request_range = REQUEST.get_header('Request-Range', None)
        if request_range is not None:
            # Netscape 2 through 4 and MSIE 3 implement a draft version
            # Later on, we need to serve a different mime-type as well.
            range = request_range
        if_range = REQUEST.get_header('If-Range', None)
        if range is not None:
            ranges = HTTPRangeSupport.parseRange(range)

            if if_range is not None:
                # Only send ranges if the data isn't modified, otherwise send
                # the whole object. Support both ETags and Last-Modified dates!
                if len(if_range) > 1 and if_range[:2] == 'ts':
                    # ETag:
                    if if_range != self.http__etag():
                        # Modified, so send a normal response. We delete
                        # the ranges, which causes us to skip to the 200
                        # response.
                        ranges = None
                else:
                    # Date
                    date = if_range.split( ';')[0]
                    try: mod_since=long(DateTime(date).timeTime())
                    except: mod_since=None
                    if mod_since is not None:
                        if self._p_mtime:
                            last_mod = long(self._p_mtime)
                        else:
                            last_mod = long(0)
                        if last_mod > mod_since:
                            # Modified, so send a normal response. We delete
                            # the ranges, which causes us to skip to the 200
                            # response.
                            ranges = None

            if ranges:
                # Search for satisfiable ranges.
                satisfiable = 0
                for start, end in ranges:
                    if start < self.size:
                        satisfiable = 1
                        break

                if not satisfiable:
                    RESPONSE.setHeader('Content-Range',
                        'bytes */%d' % self.size)
                    RESPONSE.setHeader('Accept-Ranges', 'bytes')
                    RESPONSE.setHeader('Last-Modified',
                        rfc1123_date(self._p_mtime))
                    RESPONSE.setHeader('Content-Type', self.content_type)
                    RESPONSE.setHeader('Content-Length', self.size)
                    RESPONSE.setStatus(416)
                    return ''

                ranges = HTTPRangeSupport.expandRanges(ranges, self.size)
                                
                if len(ranges) == 1:
                    # Easy case, set extra header and return partial set.
                    start, end = ranges[0]
                    size = end - start

                    RESPONSE.setHeader('Last-Modified',
                        rfc1123_date(self._p_mtime))
                    RESPONSE.setHeader('Content-Type', self.content_type)
                    RESPONSE.setHeader('Content-Length', size)
                    RESPONSE.setHeader('Accept-Ranges', 'bytes')
                    RESPONSE.setHeader('Content-Range',
                        'bytes %d-%d/%d' % (start, end - 1, self.size))
                    RESPONSE.setStatus(206) # Partial content

                    data = urllib.urlopen(self.baseUrl+self.queryString).read()
                    if type(data) is StringType:
                        return data[start:end]

                    # Linked Pdata objects. Urgh.
                    pos = 0
                    while data is not None:
                        l = len(data.data)
                        pos = pos + l
                        if pos > start:
                            # We are within the range
                            lstart = l - (pos - start)

                            if lstart < 0: lstart = 0

                            # find the endpoint
                            if end <= pos:
                                lend = l - (pos - end)

                                # Send and end transmission
                                RESPONSE.write(data[lstart:lend])
                                break

                            # Not yet at the end, transmit what we have.
                            RESPONSE.write(data[lstart:])

                        data = data.next

                    return ''

                else:
                    boundary = choose_boundary()

                    # Calculate the content length
                    size = (8 + len(boundary) + # End marker length
                        len(ranges) * (         # Constant lenght per set
                            49 + len(boundary) + len(self.content_type) +
                            len('%d' % self.size)))
                    for start, end in ranges:
                        # Variable length per set
                        size = (size + len('%d%d' % (start, end - 1)) +
                            end - start)


                    # Some clients implement an earlier draft of the spec, they
                    # will only accept x-byteranges.
                    draftprefix = (request_range is not None) and 'x-' or ''

                    RESPONSE.setHeader('Content-Length', size)
                    RESPONSE.setHeader('Accept-Ranges', 'bytes')
                    RESPONSE.setHeader('Last-Modified',
                        rfc1123_date(self._p_mtime))
                    RESPONSE.setHeader('Content-Type',
                        'multipart/%sbyteranges; boundary=%s' % (
                            draftprefix, boundary))
                    RESPONSE.setStatus(206) # Partial content

                    data = urllib.urlopen(self.baseUrl+self.queryString).read()
                    # The Pdata map allows us to jump into the Pdata chain
                    # arbitrarily during out-of-order range searching.
                    pdata_map = {}
                    pdata_map[0] = data

                    for start, end in ranges:
                        RESPONSE.write('\r\n--%s\r\n' % boundary)
                        RESPONSE.write('Content-Type: %s\r\n' %
                            self.content_type)
                        RESPONSE.write(
                            'Content-Range: bytes %d-%d/%d\r\n\r\n' % (
                                start, end - 1, self.size))

                        if type(data) is StringType:
                            RESPONSE.write(data[start:end])

                        else:
                            # Yippee. Linked Pdata objects. The following
                            # calculations allow us to fast-forward through the
                            # Pdata chain without a lot of dereferencing if we
                            # did the work already.
                            first_size = len(pdata_map[0].data)
                            if start < first_size:
                                closest_pos = 0
                            else:
                                closest_pos = (
                                    ((start - first_size) >> 16 << 16) +
                                    first_size)
                            pos = min(closest_pos, max(pdata_map.keys()))
                            data = pdata_map[pos]

                            while data is not None:
                                l = len(data.data)
                                pos = pos + l
                                if pos > start:
                                    # We are within the range
                                    lstart = l - (pos - start)

                                    if lstart < 0: lstart = 0

                                    # find the endpoint
                                    if end <= pos:
                                        lend = l - (pos - end)

                                        # Send and loop to next range
                                        RESPONSE.write(data[lstart:lend])
                                        break

                                    # Not yet at the end, transmit what we have.
                                    RESPONSE.write(data[lstart:])

                                data = data.next
                                # Store a reference to a Pdata chain link so we
                                # don't have to deref during this request again.
                                pdata_map[pos] = data

                    # Do not keep the link references around.
                    del pdata_map

                    RESPONSE.write('\r\n--%s--\r\n' % boundary)
                    return ''

        RESPONSE.setHeader('Last-Modified', rfc1123_date(self._p_mtime))
        RESPONSE.setHeader('Content-Type', self.content_type)
        RESPONSE.setHeader('Content-Length', self.size)
        RESPONSE.setHeader('Accept-Ranges', 'bytes')

        # Don't cache the data itself, but provide an opportunity
        # for a cache manager to set response headers.
        self.ZCacheable_set(None)

        data=urllib.urlopen(self.baseUrl+self.queryString).read()
        
        if type(data) is type(''): 
            RESPONSE.setBase(None)
            return data

        while data is not None:
            RESPONSE.write(data.data)
            data=data.next

        return ''


def manage_addZogiImageForm(self):
    """Form for adding"""
    pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiImage.zpt')).__of__(self)
    return pt()


def manage_addZogiImage(self,id,title,baseUrl, queryString,RESPONSE=None):
    """add dgilib"""
    newObj=zogiImage(id,title,baseUrl, queryString)
    self.Destination()._setObject(id,newObj)
    if RESPONSE is not None:
        RESPONSE.redirect('manage_main')



class zogiLib(Folder):
    """StandardElement"""

    meta_type="zogiLib"

    manage_options = Folder.manage_options+(
            {'label':'Main Config','action':'changeZogiLibForm'},
            )

    def __init__(self, id, title, digilibBaseUrl, localFileBase, version="book", basePath=""):
        """init"""

        self.id=id
        self.title=title
        self.digilibBaseUrl=digilibBaseUrl
        self.localFileBase=localFileBase
        self.basePath=basePath
        self.layout=version


    def getDLInfo(self):
        """get DLInfo from digilib server"""
        paramH={}
        baseUrl=re.sub("servlet/Scaler","dlInfo-xml.jsp",self.digilibBaseUrl)
        try:
            url=urllib.urlopen(baseUrl+self.REQUEST['QUERY_STRING'])
            dom=xml.dom.minidom.parse(url)
            params=dom.getElementsByTagName('parameter')
            for param in params:
                paramH[param.getAttribute('name')]=param.getAttribute('value')
            return paramH
        except:
            return null


    def createHeadJS(self):
        """generate all javascript tags for head"""
        pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogilib_head_js')).__of__(self)
        return pt()

    def createParamJS(self):
        """generate javascript for parameters only"""
        pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogilib_param_js')).__of__(self)
        return pt()
        
                        
    def createScalerImg(self, requestString = None, bottom = 0, side = 0):
        """generate Scaler IMG Tag"""
	self.checkQuery()
	bt = self.REQUEST.SESSION['browserType']
        if not requestString:
            requestString = self.getAllDLParams()
        url = self.digilibBaseUrl+requestString
        tag = ""
        if bt.isN4:
            tag += '<ilayer id="scaler">'
        else:
            tag += '<div id="scaler">'
        tag += '<script type="text/javascript">'
        tag += "var ps = bestPicSize(getElement('scaler'));"
        b_par = ""
        s_par = ""
        if (bottom != 0) or (side != 0):
            b_par = "-" + str(int(bottom))
            s_par = "-" + str(int(side))
        tag += 'document.write(\'<img id="pic" src="%s&dw=\'+(ps.width%s)+\'&dh=\'+(ps.height%s)+\'" />\')'%(url, s_par, b_par)
        tag += '</script>'
        if bt.isN4:
            tag += '</ilayer>'
        else:
            tag += '</div>'
        return tag

    def createAuxDiv(self):
        """generate other divs"""
	self.checkQuery()
	bt = self.REQUEST.SESSION['browserType']
        if bt.isN4:
            f = 'zpt/zogilib_divsN4.zpt'
        else:
            f = 'zpt/zogilib_divs.zpt'
        pt=PageTemplateFile(os.path.join(package_home(globals()),f)).__of__(self)
        return pt()


    def option_js(self):
        """option_js"""
        pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/option_js')).__of__(self)
        return pt()

    def dl_lib_js(self):
        """javascript"""
        return sendFile(self, 'js/dl_lib.js', 'text/plain')

    def js_lib_js(self):
        """javascript"""
        return sendFile(self, 'js/js_lib.js', 'text/plain')

    def optionwindow(self):
        """showoptions"""
        pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/optionwindow.zpt')).__of__(self)
        return pt()

    def mark1(self):
        """mark image"""
        return sendFile(self, 'images/mark1.gif', 'image/gif')

    def mark2(self):
        """mark image"""
        return sendFile(self, 'images/mark2.gif', 'image/gif')

    def mark3(self):
        """mark image"""
        return sendFile(self, 'images/mark3.gif', 'image/gif')

    def mark4(self):
        """mark image"""
        return sendFile(self, 'images/mark4.gif', 'image/gif')

    def mark5(self):
        """mark image"""
        return sendFile(self, 'images/mark5.gif', 'image/gif')

    def mark6(self):
        """mark image"""
        return sendFile(self, 'images/mark6.gif', 'image/gif')

    def mark7(self):
        """mark image"""
        return sendFile(self, 'images/mark7.gif', 'image/gif')

    def mark8(self):
        """mark image"""
        return sendFile(self, 'images/mark8.gif', 'image/gif')

    def corner1(self):
        """mark image"""
        return sendFile(self, 'images/olinks.gif', 'image/gif')

    def corner2(self):
        """mark image"""
        return sendFile(self, 'images/orechts.gif', 'image/gif')

    def corner3(self):
        """mark image"""
        return sendFile(self, 'images/ulinks.gif', 'image/gif')

    def corner4(self):
        """mark image"""
        return sendFile(self, 'images/urechts.gif', 'image/gif')



            
    def index_html(self):
        """main action"""
        tp = "zogiLibMainTemplate"
        if hasattr(self, tp):
	    pt = getattr(self, tp)
        else:
            pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/zogiLibMain_%s'%self.layout)).__of__(self)
        return pt()



    def storeQuery(self, more = None):
        """storeQuery in session"""
        dlParams = {}
        for fm in self.REQUEST.form.keys():
            dlParams[fm] = self.REQUEST.form[fm]
        # look for more
        if more:
            for fm in more.split('&'):
                try:
                    pv = fm.split('=')
                    dlParams[pv[0]] = pv[1]
                except:
                    print "ouch!"
        # parse digilib mode parameter
        if 'mo' in dlParams:
            if len(dlParams['mo']) > 0:
                modes=dlParams['mo'].split(',')
        else:
            modes=[]

        self.REQUEST.SESSION['query'] = dlParams
        self.REQUEST.SESSION['dlModes'] = modes
        self.REQUEST.SESSION['dlInfo'] = self.getDLInfo()
        self.REQUEST.SESSION['browserType'] = BrowserCheck(self)

    def checkQuery(self):
	"""check if the query has been stored"""
	if not (self.REQUEST.SESSION):
	    print "ZOGILIB: have to store query!!"
	    storeQuery(self)
        
    def getDLParam(self,param):
        """returns parameter"""
        try:
            return self.REQUEST.SESSION['query'][param]
        except:
            return None

    def setDLParam(self, param, value):
        """sets parameter"""
        self.REQUEST.SESSION['query'][param] = value
        return

    def getAllDLParams(self):
        """parameter string for digilib"""
        dlParams = self.REQUEST.SESSION['query']
        # save modes
        modes = self.REQUEST.SESSION['dlModes']
        dlParams['mo'] = string.join(modes, ',')
        # assemble query string
        ret = ""
        for param in dlParams.keys():
            val = str(dlParams[param])
            if val != "":
                ret += param + "=" + val + "&"
        # omit trailing "&"
        return ret.rstrip('&')

        
    def setDLParams(self,pn=None,ws=None,rot=None,brgt=None,cont=None):
        """setze Parameter"""
        ret=""

        if brgt:
            self.setDLParam('brgt', brgt)

        if cont:
            self.setDLParam('cont', cont)

        if pn:
            # unmark
            self.setDLParam('mk', None)
            self.setDLParam('pn', pn)

        if ws:
            self.setDLParam('ws', ws)

        if rot:
            self.setDLParam('rot', rot)
            
        return self.display()


    def display(self):
        """(re)display page"""
        params = self.getAllDLParams()
        if self.basePath:
            self.REQUEST.RESPONSE.redirect(self.REQUEST['URL2']+'?'+params)
        else:
            self.REQUEST.RESPONSE.redirect(self.REQUEST['URL1']+'?'+params)

    def getPT(self):
        """pagenums"""
        di = self.REQUEST.SESSION['dlInfo']
        if di:
            return int(di['pt'])
        else:
            return 1
    
    def getPN(self):
        """Pagenum"""
        pn = self.getDLParam('pn')
        if pn:
            return int(pn)
        else:
            return 1

    def getBiggerWS(self):
        """ws+1"""
        ws=self.getDLParam('ws')
        if ws:
            return int(ws)+1
        else:
            return 2

        
    def getSmallerWS(self):
        """ws-1"""
        ws=self.getDLParam('ws')
        if ws:
            if int(ws)==1:
                return 1
            else:
                return int(ws)-1
        else:
            return 1

    def hasMode(self, mode):
        """returns if mode is in the diglib mo parameter"""
        return (mode in self.REQUEST.SESSION['dlModes'])

    def hasNextPage(self):
        """returns if there is a next page"""
        pn = self.getPN()
        pt = self.getPT()
        return (pn < pt)
   
    def hasPrevPage(self):
        """returns if there is a previous page"""
        pn = self.getPN()
        return (pn > 1)

   
        
    def dl_HMirror(self):
        """mirror action"""
        modes = self.REQUEST.SESSION['dlModes']
        if 'hmir' in modes:
            modes.remove('hmir')
        else:
            modes.append('hmir')

        return self.display()
       
    def dl_VMirror(self):
        """mirror action"""
        modes = self.REQUEST.SESSION['dlModes']
        if 'vmir' in modes:
            modes.remove('vmir')
        else:
            modes.append('vmir')

        return self.display()

    def dl_WholePage(self):
        """zoom out action"""
        self.setDLParam('ww', 1)
        self.setDLParam('wh', 1)
        self.setDLParam('wx', 0)
        self.setDLParam('wy', 0)
        return self.display()
        
    def dl_PrevPage(self):
        """next page action"""
        pn = self.getPN() - 1
        if pn < 1:
            pn = 1
        self.setDLParam('pn', pn)
        # unmark
        self.setDLParam('mk', None)
        return self.display()
        
    def dl_NextPage(self):
        """next page action"""
        pn = self.getPN() + 1
        pt = self.getPT()
        if pn > pt:
            pn = pt
        self.setDLParam('pn', pn)
        # unmark
        self.setDLParam('mk', None)
        return self.display()

    def dl_FirstPage(self):
        """first page action"""
        self.setDLParam('pn', 1)
        # unmark
        self.setDLParam('mk', None)
        return self.display()
    
    def dl_LastPage(self):
        """last page action"""
        self.setDLParam('pn', self.getPT())
        # unmark
        self.setDLParam('mk', None)
        return self.display()

    def dl_Unmark(self):
        """action to remove last mark"""
        mk = self.getDLParam('mk')
        if mk:
            marks = mk.split(',')
            marks.pop()
            mk = string.join(marks, ',')
            self.setDLParam('mk', mk)
        return self.display()



    def changeZogiLibForm(self):
        """Main configuration"""
        pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/changeZogiLibForm.zpt')).__of__(self)
        return pt()
    
    def changeZogiLib(self,title,digilibBaseUrl, localFileBase, version, basePath, RESPONSE=None):
        """change it"""
        self.title=title
        self.digilibBaseUrl=digilibBaseUrl
        self.localFileBase=localFileBase
        self.basePath = basePath
        self.layout=version

        if RESPONSE is not None:
            RESPONSE.redirect('manage_main')

          
def manage_addZogiLibForm(self):
    """interface for adding zogilib"""
    pt=PageTemplateFile(os.path.join(package_home(globals()), 'zpt/addZogiLibForm')).__of__(self)
    return pt()

def manage_addZogiLib(self,id,title,digilibBaseUrl, localFileBase,version="book",basePath="",RESPONSE=None):
    """add dgilib"""
    newObj=zogiLib(id,title,digilibBaseUrl, localFileBase, version, basePath)
    self.Destination()._setObject(id,newObj)
    if RESPONSE is not None:
        RESPONSE.redirect('manage_main')

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