Annotation of cdli/cdli_files.py, revision 1.102

1.22      dwinter     1: """CDLI extensions of the filearchive"""    
1.47      dwinter     2: from Products.versionedFile.extVersionedFile import *
1.1       dwinter     3: from Products.ZCatalog.CatalogPathAwareness import CatalogAware
                      4: import os.path
                      5: import os
1.3       dwinter     6: import urlparse
1.49      dwinter     7: import urllib
                      8: import cgi
1.4       dwinter     9: from OFS.OrderedFolder import OrderedFolder
                     10: from OFS.SimpleItem import SimpleItem
                     11: import time
1.12      dwinter    12: from OFS.Folder import manage_addFolder
                     13: import re
1.19      dwinter    14: from AccessControl import ClassSecurityInfo
                     15: from Acquisition import Implicit
1.39      dwinter    16: from Globals import Persistent
1.19      dwinter    17: from threading import Thread
                     18: from ZPublisher.HTTPRequest import HTTPRequest
                     19: from ZPublisher.HTTPResponse import HTTPResponse
                     20: from ZPublisher.BaseRequest import RequestContainer
1.20      dwinter    21: import threading
1.83      dwinter    22: from BTrees.OOBTree import OOBTree, OOTreeSet
1.57      dwinter    23: import logging
1.58      dwinter    24: import transaction
1.61      dwinter    25: import copy
1.66      dwinter    26: import codecs
1.76      dwinter    27: import sys
1.83      dwinter    28: from BTrees.IOBTree import IOBTree 
1.81      casties    29: import cdliSplitter
1.83      dwinter    30: from sets import Set
                     31: import md5
1.87      dwinter    32: from DownloadBasket import DownloadBasketFinallyThread
1.102   ! dwinter    33: from types import *
1.85      dwinter    34:                                        
                     35: def makelist(mySet):
                     36:         x = list(mySet)
                     37:         x.sort()
                     38:         return x
                     39:     
1.79      casties    40: def unicodify(s):
                     41:     """decode str (utf-8 or latin-1 representation) into unicode object"""
                     42:     if not s:
                     43:         return u""
                     44:     if isinstance(s, str):
                     45:         try:
                     46:             return s.decode('utf-8')
                     47:         except:
                     48:             return s.decode('latin-1')
                     49:     else:
                     50:         return s
                     51: 
                     52: def utf8ify(s):
                     53:     """encode unicode object or string into byte string in utf-8 representation.
                     54:        assumes string objects to be utf-8"""
                     55:     if not s:
                     56:         return ""
                     57:     if isinstance(s, str):
                     58:         return s
                     59:     else:
                     60:         return s.encode('utf-8')
                     61: 
1.81      casties    62: def formatAtfHtml(l):
                     63:     """escape special ATF characters for HTML"""
                     64:     if not l:
                     65:         return ""
                     66: 
                     67:     # replace &
                     68:     l = l.replace('&','&')
                     69:     # replace angular brackets
                     70:     l = l.replace('<','&lt;')
                     71:     l = l.replace('>','&gt;')
                     72:     return l
                     73: 
                     74: def formatAtfLineHtml(l, nolemma=True):
                     75:     """format ATF line for HTML"""
                     76:     if not l:
                     77:         return ""
                     78: 
                     79:     if nolemma:
                     80:         # ignore lemma lines
                     81:         if l.lstrip().startswith('#lem:'):
                     82:             return ""
                     83:     
                     84:     return formatAtfHtml(l)
                     85: 
1.79      casties    86: 
1.81      casties    87: 
                     88: def formatAtfFullLineNum(txt, nolemma=True):
                     89:     """format full line numbers in ATF text"""
                     90:     # surface codes
                     91:     surfaces = {'@obverse':'obv',
                     92:                 '@reverse':'rev',
                     93:                 '@surface':'surface',
                     94:                 '@edge':'edge',
                     95:                 '@left':'left',
                     96:                 '@right':'right',
                     97:                 '@top':'top',
                     98:                 '@bottom':'bottom',
                     99:                 '@face':'face',
                    100:                 '@seal':'seal'}
                    101: 
                    102:     if not txt:
                    103:         return ""
                    104:     
                    105:     ret = []
                    106:     surf = ""
                    107:     col = ""
                    108:     for line in txt.splitlines():
                    109:         line = unicodify(line)
                    110:         if line and line[0] == '@':
                    111:             # surface or column
                    112:             words = line.split(' ')
                    113:             if words[0] in surfaces:
                    114:                 surf = line.replace(words[0],surfaces[words[0]]).strip()
                    115:             
                    116:             elif words[0] == '@column':
                    117:                 col = ' '.join(words[1:])
                    118:             
                    119:         elif line and line[0] in '123456789':
                    120:             # ordinary line -> add line number
                    121:             line = "%s:%s:%s"%(surf,col,line)
                    122:             
                    123:         ret.append(line)
                    124:     
                    125:     return '\n'.join(ret)
                    126:             
                    127:             
1.73      dwinter   128: def generateXMLReturn(hash):
                    129:     """erzeugt das xml file als returnwert fuer uploadATFRPC"""
                    130: 
                    131:     ret="<return>"
                    132:     
                    133:     ret+="<errors>"
                    134:     for error in hash['errors']:
                    135:         ret+="""<error atf="%s">%s</error>"""%error
                    136:     
                    137:     ret+="</errors>"
                    138:     
                    139:     ret+="<changes>"
                    140:     for changed in hash['changed']:
                    141:         ret+="""<change atf="%s">%s</change>"""%changed
                    142:     ret+="</changes>"
                    143:     
                    144:     ret+="<newPs>"
                    145:     for new in hash['newPs']:
                    146:         ret+="""<new atf="%s"/>"""%new
                    147:     ret+="</newPs>"
                    148:     
                    149:     ret+="</return>"
                    150:     return ret
                    151:     
                    152:     
1.55      dwinter   153: def unique(s):
                    154:     """Return a list of the elements in s, but without duplicates.
                    155: 
                    156:     For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
                    157:     unique("abcabc") some permutation of ["a", "b", "c"], and
                    158:     unique(([1, 2], [2, 3], [1, 2])) some permutation of
                    159:     [[2, 3], [1, 2]].
                    160: 
                    161:     For best speed, all sequence elements should be hashable.  Then
                    162:     unique() will usually work in linear time.
                    163: 
                    164:     If not possible, the sequence elements should enjoy a total
                    165:     ordering, and if list(s).sort() doesn't raise TypeError it's
                    166:     assumed that they do enjoy a total ordering.  Then unique() will
                    167:     usually work in O(N*log2(N)) time.
                    168: 
                    169:     If that's not possible either, the sequence elements must support
                    170:     equality-testing.  Then unique() will usually work in quadratic
                    171:     time.
                    172:     (from the python cookbook)
                    173:     """
                    174: 
                    175:     n = len(s)
                    176:     if n == 0:
                    177:         return []
                    178: 
                    179:     # Try using a dict first, as that's the fastest and will usually
                    180:     # work.  If it doesn't work, it will usually fail quickly, so it
                    181:     # usually doesn't cost much to *try* it.  It requires that all the
                    182:     # sequence elements be hashable, and support equality comparison.
                    183:     u = {}
                    184:     try:
                    185:         for x in s:
                    186:             u[x] = 1
                    187:     except TypeError:
                    188:         del u  # move on to the next method
                    189:     else:
                    190:         return u.keys()
                    191: 
                    192:     # We can't hash all the elements.  Second fastest is to sort,
                    193:     # which brings the equal elements together; then duplicates are
                    194:     # easy to weed out in a single pass.
                    195:     # NOTE:  Python's list.sort() was designed to be efficient in the
                    196:     # presence of many duplicate elements.  This isn't true of all
                    197:     # sort functions in all languages or libraries, so this approach
                    198:     # is more effective in Python than it may be elsewhere.
                    199:     try:
                    200:         t = list(s)
                    201:         t.sort()
                    202:     except TypeError:
                    203:         del t  # move on to the next method
                    204:     else:
                    205:         assert n > 0
                    206:         last = t[0]
                    207:         lasti = i = 1
                    208:         while i < n:
                    209:             if t[i] != last:
                    210:                 t[lasti] = last = t[i]
                    211:                 lasti += 1
                    212:             i += 1
                    213:         return t[:lasti]
                    214: 
                    215:     # Brute force is all that's left.
                    216:     u = []
                    217:     for x in s:
                    218:         if x not in u:
                    219:             u.append(x)
                    220:     return u
                    221: 
                    222: 
1.39      dwinter   223: class BasketContent(SimpleItem):
                    224:     """classe fuer den Inhalt eines Baskets"""
1.77      dwinter   225:    
1.102   ! dwinter   226:     def getFileAndVersionFromId(self,pnum,versionNr):
        !           227:        
        !           228:         obj=self.cdliRoot.getFileObject(pnum)
        !           229:         logging.debug("obj : %s"%obj)
        !           230:         version=obj.getVersionNr(versionNr)
        !           231:         logging.debug("-------vs: %s"%version.getFileName())
        !           232:         return version,obj
        !           233:     
1.39      dwinter   234:     def __init__(self,content=[]):
                    235:         """content"""
1.102   ! dwinter   236:         
        !           237:         self.setContent(content[0:])
1.39      dwinter   238:     
1.99      dwinter   239:     def getContent(self,filtered=True):
1.102   ! dwinter   240:         return self.contentList
        !           241:     
        !           242:     def getContentOld(self,filtered=True):
1.39      dwinter   243:         """get content"""
1.102   ! dwinter   244:         logging.debug("content object: content List %s"%self.contentList)
1.99      dwinter   245:         ret=[]
1.102   ! dwinter   246:         
        !           247:         return [self.getFileAndVersionFromId(x[0],x[1]) for x in self.contentList]
        !           248: #            
        !           249: #      if filtered:
        !           250: #          for x in self.contentList:
        !           251: #                    if not((x[0] is None) or (x[1] is None)):
        !           252: #                            ret.append(x)
        !           253: #            logging.debug("content object: content List -done filtered")
        !           254: #            return ret
        !           255: #          
        !           256: #      else:
        !           257: #            logging.debug("content object: content List -done  not filtered")
        !           258: #          return self.contentList
1.99      dwinter   259: 
                    260:     def allContent(self):
                    261:         """get all content"""
                    262:         return self.getContent(filtered=False)
                    263: 
1.39      dwinter   264:     def setContent(self,content):
1.102   ! dwinter   265:         contentList=[]
        !           266:         for x in content:
        !           267:             if not((x[0] is None) or (x[1] is None)):
        !           268:             
        !           269:                 contentList.append((x[1].getId(),x[0].getVersionNumber()))
        !           270:         logging.debug("cl: %s"%contentList)
        !           271:         self.contentList=contentList[0:]
        !           272:    
1.39      dwinter   273:     def numberOfItems(self):
                    274:         """number"""
                    275:         
                    276:         return len(self.getContent())
                    277:         
                    278:     
1.19      dwinter   279: class uploadATFfinallyThread(Thread):
1.20      dwinter   280:     """class for adding uploaded filed (temporarily stored in the staging area at /tmp"""
                    281:     
1.19      dwinter   282:     def __init__(self):
1.20      dwinter   283:         """init for uploadATFfinallyThread"""
1.19      dwinter   284:         self.continueVar=True
                    285:         self.returnValue=None
                    286:         self.end=False
                    287:         Thread.__init__(self)
                    288:            
                    289:     def set(self,procedure,comment="",basketname='',unlock=None,SESSION=None,username=None,serverport="8080"):
1.20      dwinter   290:         """set start values for the thread"""
1.19      dwinter   291:         self.procedure=procedure
                    292:         self.comment=comment
                    293:         self.basketname=basketname
                    294:         self.unlock=unlock
                    295:         self.SESSION=SESSION
                    296:         self.username=username
                    297:         self.serverport=serverport
1.60      dwinter   298:        
1.19      dwinter   299:         
                    300:     def __call__(self):
1.20      dwinter   301:         """call of the thread (equals run)"""
1.19      dwinter   302:         self.run()
                    303:         return True
                    304:     
                    305:     def getContext(self, app,serverport="8080"):
1.20      dwinter   306:         """get the context within the ZODB"""
                    307:         
1.19      dwinter   308:         resp = HTTPResponse(stdout=None)
                    309:         env = {
                    310:             'SERVER_NAME':'localhost',
                    311:             'SERVER_PORT':serverport,
                    312:             'REQUEST_METHOD':'GET'
                    313:             }
                    314:         req = HTTPRequest(None, env, resp)
                    315:         return app.__of__(RequestContainer(REQUEST = req))
                    316:           
1.26      dwinter   317:         
1.19      dwinter   318:     def run(self):
1.20      dwinter   319:         """run"""
                    320:         
1.19      dwinter   321:         self.result=""
1.20      dwinter   322:         #find context within ZODB
1.19      dwinter   323:         from Zope import DB
                    324:         conn = DB.open()
                    325:         root = conn.root()
                    326:         app  = root['Application']
                    327:         ctx = self.getContext(app,serverport=self.serverport)
                    328: 
1.20      dwinter   329:         #add the files
1.19      dwinter   330:         self.uploadATFfinallyThread(ctx,self.procedure,comment=self.comment,basketname=self.basketname,unlock=self.unlock,SESSION=self.SESSION,username=self.username)
1.20      dwinter   331:         #commit the transactions
1.58      dwinter   332:         transaction.get().commit()
1.19      dwinter   333:         conn.close()
1.20      dwinter   334:         #set flag for end of this method
1.19      dwinter   335:         self.end=True
1.66      dwinter   336:         logging.info("ended")
                    337:         return True
1.19      dwinter   338:     
1.22      dwinter   339:     def __del__(self):
                    340:         """delete"""
                    341:         
                    342:         
                    343:     
1.19      dwinter   344:     def getResult(self):
1.20      dwinter   345:         """method for accessing result"""
                    346:         
1.19      dwinter   347:         return self.result
                    348:      
                    349:     def uploadATFfinallyThread(self,ctx,procedure,comment="",basketname='',unlock=None,RESPONSE=None,SESSION=None,username=None):
                    350:         """upload the files"""
1.20      dwinter   351:         #TODO: make this configurable, at the moment, rootFolder for cdli has to be cdliRoot
1.19      dwinter   352:         ctx2=ctx.cdliRoot
                    353:    
                    354:         self.result+="<h2>Start processing</h2>"
1.20      dwinter   355:         
                    356:         #shall I only upload the changed files?
1.81      casties   357:         logging.debug("uploadATFfinally procedure: %s"%procedure)
1.19      dwinter   358:         if procedure=="uploadchanged":
1.66      dwinter   359:             changed=[x[0] for x in SESSION.get('changed',[])]
1.61      dwinter   360:             uploadFns=changed+SESSION.get('newPs',[])
1.19      dwinter   361:         
1.20      dwinter   362:         #or all
1.19      dwinter   363:         elif procedure=="uploadAll":
                    364:             uploadFns=[]
                    365:             for x in os.listdir(SESSION['tmpdir']):
1.45      dwinter   366:                 if not x in SESSION['lockerrors']:
1.19      dwinter   367:                     uploadFns.append(x)
1.20      dwinter   368:                     
                    369:         #or maybe nothing
1.19      dwinter   370:         elif procedure=="noupload":
1.81      casties   371:             return True
1.19      dwinter   372:         else:
                    373:             uploadFns=[]
                    374:             
1.20      dwinter   375:         #do first the changed files    
1.65      dwinter   376:         i=0
1.19      dwinter   377:         for fn in uploadFns:
1.81      casties   378:             logging.debug("uploadATFfinally uploadFn=%s"%fn)
1.66      dwinter   379:             i+=1
1.19      dwinter   380:             founds=ctx2.CDLICatalog.search({'title':fn})
                    381:             if len(founds)>0:
                    382:                 SESSION['author']=str(username)
1.63      dwinter   383:                 self.result="<p>Changing : %s"%fn+self.result
1.81      casties   384:                 logging.debug("uploadatffinallythread changing:%s"%fn+self.result)
1.49      dwinter   385:                 founds[0].getObject().manage_addCDLIFileObject('',comment,SESSION['author'],file=os.path.join(SESSION['tmpdir'],fn),from_tmp=True)
1.81      casties   386:             if i%200==0:
                    387:                 transaction.get().commit()
                    388:                 logging.debug("uploadatffinallythread changing: do commit")
1.65      dwinter   389:         
                    390:         transaction.get().commit()
1.81      casties   391:         logging.debug("uploadatffinallythread changing: last commit")
1.62      dwinter   392: 
1.20      dwinter   393:         #now add the new files        
1.19      dwinter   394:         newPs=SESSION['newPs']
                    395:         if len(newPs)>0:
                    396:             tmpDir=SESSION['tmpdir']
1.81      casties   397:             logging.debug("uploadatffinallythread adding start")
1.63      dwinter   398:             self.result="<p>Adding files</p>"+self.result
1.20      dwinter   399:             #TODO: make this configurable, at the moment base folder for the files has to be cdli_main
1.22      dwinter   400:             ctx2.importFiles(comment=comment,author=str(username) ,folderName=tmpDir, files=newPs,ext=self)
1.81      casties   401:             logging.debug("uploadatffinallythread adding finished")
1.19      dwinter   402:         
1.20      dwinter   403:         #unlock locked files?
1.19      dwinter   404:         if unlock:
1.81      casties   405:             logging.debug("uploadatffinallythread unlocking start")
1.63      dwinter   406:             self.result="<p>Unlock files</p>"+self.result
1.19      dwinter   407:             unlockFns=[]
                    408:             for x in os.listdir(SESSION['tmpdir']):
                    409:                     if not x in SESSION['errors']:
                    410:                         unlockFns.append(x)
1.81      casties   411:                         
                    412:             logging.debug("unlocking have now what to unlock")
1.65      dwinter   413:                         
1.19      dwinter   414:             for fn in unlockFns:
1.65      dwinter   415:                 #logging.info("will unlock: %s"%fn)
1.19      dwinter   416:                 founds=ctx2.CDLICatalog.search({'title':fn})
1.65      dwinter   417:                 #logging.info("found it: %s"%repr(founds))
1.19      dwinter   418:                 if len(founds)>0:
1.65      dwinter   419:                     #logging.info("unlock: %s"%founds[0].getObject().getId())
1.19      dwinter   420:                     SESSION['author']=str(username)
                    421:                     founds[0].getObject().lockedBy=""
1.81      casties   422: 
                    423:             logging.debug("uploadatffinallythread unlocking done")
1.19      dwinter   424:                     
1.65      dwinter   425:         #if a basketname is given, add files to the basket
1.19      dwinter   426:         if not (basketname ==''):
1.81      casties   427:             logging.debug("uploadatffinallythread add to basket %s"%basketname)
1.65      dwinter   428:             self.result="<p>Add to basket</p>"+self.result
1.41      dwinter   429:             basketId=ctx2.basketContainer.getBasketIdfromName(basketname)
1.19      dwinter   430:             
                    431:             if not basketId: # create new basket
1.81      casties   432:                 logging.debug("uploadatffinallythread create basket %s"%basketname)
1.65      dwinter   433:                 self.result="<p>Create a new basket</p>"+self.result
1.19      dwinter   434:                 ob=ctx2.basketContainer.addBasket(basketname)
                    435:                 basketId=ob.getId()
                    436:             basket=getattr(ctx2.basketContainer,str(basketId))
                    437:             ids=os.listdir(SESSION['tmpdir'])
1.93      dwinter   438:             #logging.debug("should add:"+repr(ids))
1.19      dwinter   439:             basket.addObjects(ids,deleteOld=True,username=str(username))    
                    440:                
1.81      casties   441:         logging.debug("uploadatffinallythread uploadfinally done")
                    442: 
1.19      dwinter   443:         if RESPONSE is not None:
                    444:             RESPONSE.redirect(self.aq_parent.absolute_url())
                    445:         
                    446:         return True
1.60      dwinter   447: 
                    448: class tmpStore(SimpleItem):
                    449:     """simple item"""
                    450:     meta_type="cdli_upload"
1.19      dwinter   451:     
1.60      dwinter   452:     def __init__(self,id):
                    453:         """init tmp"""
                    454:         self.id=id
                    455:         
1.19      dwinter   456: class uploadATFThread(Thread):
1.20      dwinter   457:     """class for checking the files befor uploading"""
1.19      dwinter   458:     
                    459:     def __init__(self):
1.20      dwinter   460:         """initialise"""
                    461:         
1.19      dwinter   462:         self.continueVar=True
                    463:         self.returnValue=None
                    464:         
                    465:         Thread.__init__(self)
                    466:         
                    467:         
1.60      dwinter   468:     def set(self,upload,basketId,username,idTmp,serverport="8080"):
1.20      dwinter   469:         """set start values for the thread"""
1.19      dwinter   470:         self.result=""
                    471:         self.upload=upload
                    472:         self.basketId=basketId
                    473:         self.username=username
                    474:         self.serverport=serverport
1.60      dwinter   475:         self.idTmp=idTmp
1.19      dwinter   476:         
                    477:     def __call__(self):
1.20      dwinter   478:         """call method """
1.19      dwinter   479:         self.run()
                    480:         return True
                    481:     
                    482:     def getContext(self, app,serverport="8080"):
1.20      dwinter   483:         """get the context within the ZODB"""
1.19      dwinter   484:         resp = HTTPResponse(stdout=None)
                    485:         env = {
                    486:             'SERVER_NAME':'localhost',
                    487:             'SERVER_PORT':serverport,
                    488:             'REQUEST_METHOD':'GET'
                    489:             }
                    490:         req = HTTPRequest(None, env, resp)
                    491:         return app.__of__(RequestContainer(REQUEST = req))
                    492:         
                    493:     def run(self):
1.60      dwinter   494:         idTmp=self.idTmp
1.19      dwinter   495:         self.result=""
1.20      dwinter   496:         #find context within ZODB
1.19      dwinter   497:         from Zope import DB
                    498:         conn = DB.open()
                    499:         root = conn.root()
                    500:         app  = root['Application']
                    501:         ctx = self.getContext(app,serverport=self.serverport)
1.60      dwinter   502:         logging.info("run intern")
1.63      dwinter   503:         try:
1.73      dwinter   504:             logging.info("created: %s"%idTmp)
1.63      dwinter   505:             ctx.temp_folder._setObject(idTmp,tmpStore(idTmp))
                    506:         except:
                    507:             logging.error("thread upload: %s %s"%sys.exc_info()[0:2])
                    508:             
1.60      dwinter   509:         logging.info("call thread intern")
                    510:         self.uploadATFThread(ctx,self.upload,idTmp,self.basketId)
1.24      dwinter   511:      
1.30      dwinter   512:         #ctx.cdliRoot.cdli_main.tmpStore2[self.getName()[0:]]=self.returnValue
1.58      dwinter   513:         
1.66      dwinter   514:         
1.58      dwinter   515:         transaction.get().commit()
1.49      dwinter   516:        
1.19      dwinter   517:         conn.close()
1.22      dwinter   518:         
1.73      dwinter   519:         return getattr(ctx.temp_folder,idTmp)
1.19      dwinter   520:         
                    521:     def getResult(self):
1.20      dwinter   522:         """method for accessing result"""
1.19      dwinter   523:         return self.result
                    524:     
1.60      dwinter   525:     def uploadATFThread(self,ctx,upload,idTmp,basketId=0):
1.19      dwinter   526:         """upload an atf file"""
                    527:         #TODO: add comments
                    528:         #TODO: finish uploadATF
1.60      dwinter   529:         
                    530:         stObj=getattr(ctx.temp_folder,idTmp)
                    531:         logging.info("start, upload thread")
1.25      dwinter   532:         self.result="<html><body><h2>I got your file, start now to split it into single atf-files!</h2><p>"
                    533:     
1.20      dwinter   534:         #make sure that id is a string and not an integer
1.19      dwinter   535:         basketId=str(basketId)
                    536:         
1.20      dwinter   537:         #TODO: make this configurable, at the moment, rootFolder for cdli has to be cdliRoot
                    538:         ctx2=ctx.cdliRoot
1.19      dwinter   539:         
1.20      dwinter   540:         #get temporary file for staging the downloaded and splitted files
1.19      dwinter   541:         dir=mkdtemp()
1.20      dwinter   542:         
                    543:         
                    544:         changed=[] # changed files
                    545:         errors=[]  # files with errors
1.45      dwinter   546:         lockerrors=[]  # files with errors
                    547: 
1.20      dwinter   548:         newPs=[]   # new p filed
                    549:         psNotInCatalog=[] # files not in the catalog
                    550:         
                    551:         #split the uploadedd atf file
1.25      dwinter   552:         basketNameFromFile, numberOfFiles=splitatf(upload,dir,ext=self)
1.19      dwinter   553:         
1.20      dwinter   554:         #find basketId if not set
                    555:         
                    556:         #get active abaket
1.19      dwinter   557:         if basketId == '0':
                    558:             basketObj=ctx2.basketContainer.getActiveBasket()
                    559:             if basketObj:
                    560:                 basketId=basketObj.getId()
                    561:                 
1.45      dwinter   562:         #if there is no active basket and no basketid given, id is empty, else get besketname and length
1.19      dwinter   563:         if basketId == '0':
                    564:             basketNameFromId=""
                    565:             basketLen=0
                    566:         else:
                    567:             basketNameFromId=getattr(ctx2.basketContainer,basketId).title
                    568:             basketLen=getattr(ctx2.basketContainer,basketId).getLastVersion().numberOfItems()
                    569:             
1.60      dwinter   570:         logging.info("got the file, upload thread")
1.25      dwinter   571:         self.result+="""<html><body><h2>I got the files</h2><
                    572:                         p>I am computing the differences to the exisiting files</p>"""
1.20      dwinter   573:                                    
                    574:         #start to check the files
1.19      dwinter   575:         for fn in os.listdir(dir):
                    576:             
1.63      dwinter   577:             self.result="<p>process:%s</p>"%fn+self.result
1.19      dwinter   578:             
1.20      dwinter   579:             # check if file is in the catalog
                    580:             #TODO: checkCatalog is not implemented yet
1.19      dwinter   581:             if ctx2.cdli_main.checkCatalog(fn):
                    582:                 psNotInCatalog.append(fn)
                    583:                 
1.20      dwinter   584:             #check if p-file already at the server  
1.19      dwinter   585:             founds=ctx2.CDLICatalog.search({'title':fn})    
                    586:       
1.20      dwinter   587:             #if not than add filename to the list of newfiles
1.46      dwinter   588:             
                    589:             data=file(os.path.join(dir,fn)).read()
1.69      dwinter   590:             status,msg=checkFile(fn,data,dir)
                    591:             #status=True
                    592:             
                    593:             
1.46      dwinter   594:             if not status: # error
                    595:                 errors.append((fn,msg))
1.69      dwinter   596:             
1.46      dwinter   597:             else:
                    598:                 if len(founds)==0:
                    599:                     newPs.append(fn)
                    600: 
                    601:                 #if p file alread at the server    
                    602:                 for found in founds:
                    603:                     #analyse the differences to the actual file
                    604:                     obj=found.getObject()
                    605: 
                    606:                     if (not (str(obj.lockedBy))=='') and (not (str(obj.lockedBy)==str(self.username))):
1.63      dwinter   607:                                 lockerrors.append((fn,str(obj.lockedBy)))
1.46      dwinter   608:                     else:
                    609:                 
                    610:                         diffs=obj.diff(data)
                    611:                         if diffs[0]>0:
                    612:                             changed.append((obj,diffs)) #hochladen
1.31      dwinter   613: 
1.20      dwinter   614:         #ready, set the returnValues
1.19      dwinter   615:         self.result+="<h3>Done</h3></body></html>"
                    616:         
1.60      dwinter   617:         stObj.returnValue={}
1.19      dwinter   618:         
1.60      dwinter   619:         stObj.returnValue['errors']=errors
1.69      dwinter   620:         
1.60      dwinter   621:         stObj.returnValue['newPs']=newPs
                    622:         stObj.returnValue['tmpdir']=dir
                    623:         stObj.returnValue['basketLen']=basketLen
                    624:         stObj.returnValue['numberOfFiles']=numberOfFiles
                    625:         stObj.returnValue['basketNameFromId']=basketNameFromId
                    626:         stObj.returnValue['basketNameFromFile']=basketNameFromFile
                    627:         stObj.returnValue['basketId']=basketId
                    628:         stObj.returnValue['dir']=dir
1.61      dwinter   629:         #stObj.returnValue['changed']=copy.copy(changed)
                    630:         stObj.returnValue['changed']=[(x[0].getId(),x[1][0]) for x in changed]
                    631:         #stObj.returnValue['lockerrors']=[x[0].getId() for x in lockerrors]
1.63      dwinter   632:         stObj.returnValue['lockerrors']=[x for x in lockerrors]
1.60      dwinter   633:         self.returnValue=True
1.19      dwinter   634:         #ctx2.cdli_main.setTemp('v_uploadATF_returnValue',True)
                    635:     
1.63      dwinter   636:  
1.4       dwinter   637: class CDLIBasketContainer(OrderedFolder):
                    638:     """contains the baskets"""
                    639:     
                    640: 
1.9       dwinter   641:     security=ClassSecurityInfo()
1.4       dwinter   642:     meta_type="CDLIBasketContainer"
                    643:     
1.73      dwinter   644:     def getPNumbersOfBasket(self,basketName):
                    645:         """get all pnumbers of a basket as a list, returns an empty list if basket not found
                    646:         @param basketName: name of the basket
                    647:         """
                    648:         ret=[]
                    649:         basketId=self.getBasketIdfromName(basketName)
                    650:         if not basketId:
                    651:             return []
                    652:         
1.102   ! dwinter   653:         ob=getattr(self,basketId).getContent() #get the content of a basket
1.73      dwinter   654:         
                    655:         ret=[x[0].split(".")[0] for x in ob]
                    656:         
                    657:         return ret
                    658:     
1.77      dwinter   659:     security.declareProtected('manage','getBasketAsOneFile')       
1.73      dwinter   660:     def getBasketAsOneFile(self,basketName,current="no"):
                    661:         """returns all files of the basket combined in one file
                    662:         @param basketName: Name of the basket
                    663:         @param current: (optional) if current is set to "yes" then the most current version of 
                    664:                         all files are downloaded and not the versions of the files as stored in the basket
                    665:         """
                    666:         ret=""
                    667:         basketId=self.getBasketIdfromName(basketName)
                    668:         if not basketId:
                    669:             return ""
                    670:         
                    671:         ob=getattr(self,basketId).getLastVersion()
1.102   ! dwinter   672:         for pnum,versionNr in ob.getContent():
        !           673:             obj=self.cdliRoot.getFileObject(pnum)
        !           674:        # logging.debug("obj : %s"%obj)
        !           675:        # version=obj.getVersionNr(versionNr)
        !           676:       
1.73      dwinter   677:             if current=="no": #version as they are in the basket
1.102   ! dwinter   678:                             cur= obj.getVersionNr(versionNr)
        !           679:                             ret+=str(cur.getData())+"\n"
1.73      dwinter   680:             elif current=="yes":
                    681:                             #search current object
1.93      dwinter   682:                             #logging.debug("current: %s"%object[1].getId().split(".")[0])
1.102   ! dwinter   683:                             obj.getData()
1.73      dwinter   684:         return ret
                    685:     
1.77      dwinter   686:     security.declareProtected('manage','upDateBaskets') 
1.39      dwinter   687:     def upDateBaskets(self):
                    688:         """update content in to objects"""
                    689:         
                    690:         founds=self.ZopeFind(self,obj_metatypes=['CDLIBasketVersion'],search_sub=1)
                    691: 
                    692:         for found in founds:
                    693:             found[1].updateBasket()
                    694:         
1.32      dwinter   695:     security.declareProtected('manage','deleteBaskets')        
1.12      dwinter   696:     def deleteBaskets(self,ids=None):
                    697:         """delete baskets, i.e. move them into trash folder"""
                    698:         
1.98      dwinter   699:         if ids is None:
                    700:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','cdliError_html.zpt')).__of__(self)
                    701:             txt="Sorry, no basket selected!"
                    702:             return pt(txt=txt)
1.12      dwinter   703:         
                    704:         found=self.ZopeFind(self,obj_ids=['trash'])
                    705:         
                    706:         if len(found)<1:
                    707:             manage_addFolder(self, 'trash')
                    708:             trash=self._getOb('trash')
                    709:         else:
                    710:             trash=found[0][1]
                    711:         
                    712:         if type(ids) is not ListType:
                    713:             ids=[ids]
1.98      dwinter   714:         logging.error("XERXON:"+repr(ids))
                    715:         if len(ids)==0:
                    716:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','cdliError_html.zpt')).__of__(self)
                    717:             txt="Sorry, no basket selected!"
                    718:             return pt(txt=txt)
                    719:    
1.12      dwinter   720:         cut=self.manage_cutObjects(ids)
                    721:         trash.manage_pasteObjects(cut)
1.98      dwinter   722:         return None
1.32      dwinter   723:     security.declareProtected('manage','manageBaskets')       
1.73      dwinter   724:     def manageBaskets(self,submit,ids=None,basket1="",basket2="",joinBasket="",subtractBasket="",REQUEST=None,RESPONSE=None):
1.12      dwinter   725:         """manage baskets, delete or copy"""
                    726:         if submit=="delete":
1.98      dwinter   727:             ret= self.deleteBaskets(ids)
                    728:             if ret:
                    729:                 return ret
1.72      dwinter   730:         elif submit=="join":
1.73      dwinter   731:             flag,msg=self.joinBasket(joinBasket, ids)
1.72      dwinter   732:             logging.info("joining %s %s"%(flag,msg))
1.98      dwinter   733:             if not flag:
                    734:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','cdliError_html.zpt')).__of__(self)
                    735:                 
                    736:                 return pt(txt=msg)
                    737:        
1.72      dwinter   738:         elif submit=="subtract":
                    739:             logging.info("BBBb %s %s"%(basket1,basket2))
1.73      dwinter   740:             flag,msg=self.subtractBasket(subtractBasket, basket1,basket2)
1.72      dwinter   741:             logging.info("subtract %s %s"%(flag,msg))
1.12      dwinter   742:             
                    743:         if RESPONSE:
                    744:             RESPONSE.redirect(self.absolute_url())
1.32      dwinter   745:     
1.33      dwinter   746:     security.declareProtected('View','getBasketIdfromName')       
1.5       dwinter   747:     def getBasketIdfromName(self,basketname):
                    748:         """get id from name"""
                    749: 
                    750:         for basket in self.ZopeFind(self,obj_metatypes=["CDLIBasket"]):
                    751:             if basket[1].title==basketname:
                    752:                 return basket[0]
                    753:         else:
                    754:             None
1.9       dwinter   755:     
                    756:     security.declareProtected('manage','uploadBasket_html')        
                    757:             
1.4       dwinter   758:     def uploadBasket_html(self,basketId='0'):
                    759:         """upload an atf file, html form"""
1.9       dwinter   760:         
                    761: 
1.4       dwinter   762:         basketId=str(basketId)
                    763:         if not basketId=='0':
                    764:             basketName=getattr(self.basketContainer,basketId).title
                    765:         else:
                    766:             basketName=""
                    767:             
                    768:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadBasket_html.zpt')).__of__(self)
                    769:         return pt(basketId=basketId,basketName=basketName)
                    770:    
                    771: 
1.77      dwinter   772:     security.declareProtected('manage','index_html')    
1.4       dwinter   773:     def index_html(self):
                    774:         """stanadard ansicht"""
1.9       dwinter   775:         
                    776: 
                    777: 
1.4       dwinter   778:         ext=self.ZopeFind(self,obj_ids=["index.html"])
                    779:         if ext:
                    780:             return ext[0][1]()
                    781:         
                    782:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','BasketContainerMain')).__of__(self)
                    783:         return pt()
                    784:     
                    785:     def getStorageFolderRoot(self):
                    786:         """root des storage folders"""
                    787:         return self.cdli_main
                    788:     
                    789:     def __init__(self,id,title):
                    790:         """ init basket container"""
                    791:         self.id=id
                    792:         self.title=title
                    793:      
1.51      dwinter   794:  
1.49      dwinter   795:     def getBasketsId(self):
                    796:         """get all baskets als klartext"""
1.51      dwinter   797:         
                    798:         ret=""
1.49      dwinter   799:         baskets=self.ZopeFind(self,obj_metatypes=['CDLIBasket'])
                    800:         for basket in baskets:
                    801:             com,user,time,values = basket[1].getContentIds()
                    802:             ret+= "BASKET:"+com+"\t"+user+"\t"+time+"\n"
                    803:             for x in values:
                    804:                 ret+= x[0]+"\t"+x[1]+"\n"
1.66      dwinter   805:                 return ret
1.49      dwinter   806: 
1.4       dwinter   807:     def getBaskets(self,sortField='title'):
                    808:         """get all baskets files"""
                    809: 
                    810:         def sortName(x,y):
                    811:             return cmp(x[1].title.lower(),y[1].title.lower())
                    812: 
                    813:         def sortDate(x,y):
                    814:             return cmp(y[1].getLastVersion().getTime(),x[1].getLastVersion().getTime())
                    815: 
                    816:         
                    817:         def sortComment(x,y):
                    818: 
                    819:         
                    820:             
                    821:              try:
                    822:                 xc=getattr(x[1],'comment','ZZZZZZZZZZZZZ').lower()
                    823:              except:
                    824:                 xc='ZZZZZZZZZZZZZ'.lower()
                    825:              try:
                    826:                 yc=getattr(y[1],'comment','ZZZZZZZZZZZZZ').lower()
                    827:              except:
                    828:                 yc='ZZZZZZZZZZZZZ'.lower()
                    829:     
                    830:     
                    831:              if (xc=='') or (xc=='ZZZZZZZZZZZZZ'.lower()):
                    832:                  
                    833:                  try:
                    834:                      xc=x[1].getLastVersion().getComment().lower()
                    835:                  except:
                    836:                      xc='ZZZZZZZZZZZZZ'.lower()
                    837:                      
                    838:              if (yc=='') or (yc=='ZZZZZZZZZZZZZ'.lower()):
                    839:                  try:
                    840:                      yc=y[1].getLastVersion().getComment().lower()
                    841:                  except:
                    842:                      yc='ZZZZZZZZZZZZZ'.lower()
                    843:     
                    844:              
                    845:                  return cmp(xc,yc)
                    846:         
                    847:         def sortAuthor(x,y):
                    848:             
                    849:             return cmp(x[1].getLastVersion().getUser().lower(),y[1].getLastVersion().getUser().lower())
                    850:         
                    851:         baskets=self.ZopeFind(self,obj_metatypes=['CDLIBasket'])
                    852:         
                    853:         
                    854:         if sortField=='title':
                    855:             baskets.sort(sortName)
                    856:         elif sortField=='date':
                    857:             baskets.sort(sortDate)
                    858:         elif sortField=='author':
                    859:             baskets.sort(sortAuthor)
                    860:         elif sortField=='comment':
                    861:             baskets.sort(sortComment)
1.39      dwinter   862: 
1.4       dwinter   863:         return baskets
1.72      dwinter   864:     
                    865:         
                    866:     def subtractBasket(self,newBasket,basket1,basket2):
                    867:         """subtract basket2 from basket1 
                    868:         (i.e. newbasket will contain alle elements of basket1 which are not in basket2), 
                    869:         if basket2 contains files which are not in basket1, then theses files fill be ignored
                    870:                
                    871:         @param newbasket: name of the new basket
                    872:         @param basket1: basket where basket2 will be subtracted from
                    873:         @param basket2: see above
                    874:       
                    875:         """
1.98      dwinter   876:         
1.72      dwinter   877:         logging.info("CCCCC %s %s"%(basket1,basket2))
                    878:    
                    879:         try:
                    880:             newB=self.addBasket(newBasket)
                    881:         except:
                    882:             return False, "cannot create the new basket"
                    883:         
                    884:         
1.4       dwinter   885: 
1.72      dwinter   886:        
                    887:      
                    888:         bas2= getattr(self,basket2)            
                    889:         bas2content=bas2.getContent()
                    890:         bas2ids=[x[0] for x in bas2content]
                    891:         
                    892:        
                    893:             
                    894:         bas1= getattr(self,basket1)   
                    895:         bas1content=bas1.getContent()
                    896:         
                    897:         
                    898:         newBasketContent={}
                    899:         
                    900:         for id,version in bas1content:
                    901:             if not (id in bas2ids):
                    902:                 newBasketContent[id]=version
                    903:         
                    904:         username=self.getActualUserName()
                    905:         
                    906:         logging.info("sbc %s"%newBasketContent)
                    907:         newB.addObjectsWithVersion(newBasketContent,username=username,catalog=self.CDLICatalog)
                    908:         
                    909:         return True, ""
                    910:     
                    911:             
                    912:     def joinBasket(self,newBasket,oldBaskets):
1.71      dwinter   913:         """join two baskets
                    914:         @param newbasket: name of the new basket
                    915:         @param oldbaskets: list of baskets to be joined
                    916:         """
1.98      dwinter   917:         if oldBaskets is None:
                    918:             return False, "No Baskets selected!"
                    919:         
1.72      dwinter   920:         try:
                    921:             newB=self.addBasket(newBasket)
                    922:         except:
                    923:             return False, "cannot create the new basket"
                    924:         
                    925:         newBasketContent={}
1.98      dwinter   926:      
1.72      dwinter   927:         for ob in oldBaskets:
                    928:             x= getattr(self,ob,None)
                    929:             if x is None:
                    930:                 return False, "cannot find basket: %s"%ob
                    931:             
                    932:             ids=x.getContent() # hole den Inhalt
                    933:             
                    934:             for id,version in ids:
                    935:                 if newBasketContent.has_key(id): # p number gibt's schon
                    936:                     newBasketContent[id]=max(newBasketContent[id],version) # speichere die groessere Versionsnumber
                    937:                 else:
                    938:                     newBasketContent[id]=version
                    939:         username=self.getActualUserName()
                    940:         
                    941:         logging.info("nbc %s"%newBasketContent)
                    942:         newB.addObjectsWithVersion(newBasketContent,username=username,catalog=self.CDLICatalog)
                    943:         
                    944:         return True, ""
                    945:     
1.4       dwinter   946:     def getNewId(self):
                    947:         """createIds"""
                    948:         last=getattr(self,'last',0)
                    949:         last +=1
                    950:         while len(self.ZopeFind(self,obj_ids=[str(last)]))>0:
                    951:             last+=1
                    952:     
                    953:         self.last=last
                    954:         return last
                    955:     
1.6       dwinter   956:     def setActiveBasket(self,basketId,REQUEST=None):
1.4       dwinter   957:         """store active basketId in a cookie"""
                    958:         self.REQUEST.RESPONSE.setCookie("CDLIActiveBasket",basketId,path="/")
1.66      dwinter   959:         try:
                    960:             qs=cgi.parse_qs(REQUEST['QUERY_STRING'])
                    961:             del(qs['basketId'])
                    962:         except:
                    963:             qs={}
1.6       dwinter   964:         if REQUEST:
1.49      dwinter   965:             REQUEST.RESPONSE.redirect(REQUEST['URL1']+'?'+urllib.urlencode(qs))
1.6       dwinter   966:             
1.4       dwinter   967:     def getActiveBasket(self):
                    968:         """get active basket from cookie"""
                    969:         
                    970:         id= self.REQUEST.cookies.get('CDLIActiveBasket',None)
1.6       dwinter   971:         if id:
                    972:             obj=getattr(self,str(id),None)
                    973:         else:
                    974:             obj=None
1.4       dwinter   975:         return obj
1.6       dwinter   976:     
1.4       dwinter   977:     def getActualUserName(self):
                    978:         """get name of the actualuser"""
                    979:         return str(self.REQUEST['AUTHENTICATED_USER'])
                    980:     
1.77      dwinter   981:     security.declareProtected('manage','addBasket') 
1.4       dwinter   982:     def addBasket(self,newBasketName):
                    983:         """add a new basket"""
                    984:         
                    985:         ob=manage_addCDLIBasket(self,newBasketName)
                    986:         return ob
1.72      dwinter   987: 
1.6       dwinter   988:     def storeInBasket(self,submit,ids=None,newBasketName=None,fromFileList=None,RESPONSE=None,REQUEST=None):
1.4       dwinter   989:         """store it"""
1.6       dwinter   990:         if not ids:
                    991:             ids=self.REQUEST.SESSION['fileIds']
1.83      dwinter   992:            
                    993:         if (type(ids) is not ListType) and (not isinstance(ids,Set)):
1.4       dwinter   994:             ids=[ids]
                    995:         
1.83      dwinter   996:         if isinstance(ids,Set):
                    997:             ids=list(ids)
                    998:             
1.6       dwinter   999:         if (submit.lower()=="store in new basket") or (submit.lower()=="new basket"):
1.4       dwinter  1000:             basketRet=self.addBasket(newBasketName)
                   1001:             self.setActiveBasket(basketRet.getId())
                   1002:             basket=getattr(self,basketRet.getId())
1.6       dwinter  1003:         elif (submit.lower()=="store in active basket") or (submit.lower()=="active basket"):
1.4       dwinter  1004:             basket=self.getActiveBasket()
1.6       dwinter  1005:         
                   1006:         added=basket.addObjects(ids)
                   1007:         back=self.REQUEST['HTTP_REFERER'].split("?")[0]+"?basketName="+basket.title+"&numberOfObjects="+str(added)
                   1008:         
                   1009:         
                   1010:         if fromFileList:
1.7       dwinter  1011: 
1.83      dwinter  1012:             return self.cdli_main.findObjectsFromList(list=ids,basketName=basket.title,numberOfObjects=added)
1.6       dwinter  1013:        
1.4       dwinter  1014:         if RESPONSE:
1.6       dwinter  1015:             
1.4       dwinter  1016:             RESPONSE.redirect(back)
                   1017:             
1.6       dwinter  1018:         return True
                   1019:     
1.4       dwinter  1020: def manage_addCDLIBasketContainerForm(self):
                   1021:     """add the CDLIBasketContainer form"""
                   1022:     pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addCDLIBasketContainer.zpt')).__of__(self)
                   1023:     return pt()
                   1024: 
                   1025: def manage_addCDLIBasketContainer(self,id,title,RESPONSE=None):
                   1026:     """add the basket"""
                   1027:     ob=CDLIBasketContainer(id,title)
                   1028:     
                   1029:     self._setObject(id, ob)
                   1030:     
                   1031:     if RESPONSE is not None:
                   1032:         RESPONSE.redirect('manage_main')
                   1033: 
1.5       dwinter  1034: class CDLIBasket(Folder,CatalogAware):
1.4       dwinter  1035:     """basket"""
                   1036:     
                   1037:     meta_type="CDLIBasket"
1.5       dwinter  1038:     default_catalog="CDLIBasketCatalog"
1.4       dwinter  1039:     
1.75      dwinter  1040:     def searchInBasket(self,indexName,searchStr,regExp=False):
                   1041:         """searchInBasket"""
                   1042: 
1.81      casties  1043:         lst=self.searchInLineIndexDocs(indexName,searchStr,uniq=True,regExp=regExp) #TODO: fix this
1.75      dwinter  1044:         ret={}
                   1045:         
                   1046:         lv=self.getLastVersion()
1.76      dwinter  1047: 
                   1048: 
1.75      dwinter  1049:         for obj in lv.content.getContent():
                   1050:             id=obj[1].getId().split(".")[0]
                   1051:             if id in lst:
                   1052:         
                   1053:                 ret[id]=self.showWordInFile(id,searchStr,lineList=self.getLinesFromIndex(indexName,searchStr,id,regExp=regExp),regExp=regExp,indexName=indexName)
                   1054:         
                   1055:         
                   1056:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','searchResultsInBasket')).__of__(self)
                   1057:         return pt(result=ret,indexName=indexName,regExp=regExp,word=searchStr)
                   1058:         
                   1059:          
                   1060:  
                   1061:         
                   1062:     def searchInBasket_v1(self,searchStr):
1.74      dwinter  1063:         """search occurences of searchStr in files im basket"""
                   1064:         ret=[]
                   1065:         lv=self.getLastVersion()
                   1066:         logging.info("searching")
                   1067:         for obj in lv.content.getContent():
                   1068:             txt=obj[0].getData()
                   1069:             for x in txt.split("\n"):
                   1070:                 logging.info("search %s"%x)
                   1071:                 if re.match(searchStr,x):
                   1072:                     ret.append(x)
                   1073:         
                   1074:         return "\n".join(ret)
                   1075:                 
                   1076:             
1.4       dwinter  1077:     def getFile(self,obj):
                   1078:         return obj[1]
                   1079:     
                   1080:     def getFileLastVersion(self,obj):
                   1081:         return obj[0]
                   1082:     
1.5       dwinter  1083:     def getFileNamesInLastVersion(self):
                   1084:         """get content of the last version as list"""
                   1085:         
                   1086:         return [x[1].getId() for x in self.getLastVersion().getContent()]
                   1087:     
1.37      dwinter  1088: 
1.102   ! dwinter  1089:     def isActual(self,obj,nummer):
        !          1090:         """teste ob im basket die aktuelle version ist, obj kann entweder ein CDLIFile sein oder eine 
        !          1091:         eine pnummer, die auf ein CDLIFile verweist"""
        !          1092:         try:
        !          1093:             #logging.debug("isActual:"+repr(obj))
        !          1094:             if isinstance(obj, CDLIFile):
        !          1095:                 actualNo=obj.getLastVersion().getVersionNumber()
        !          1096:             else:
        !          1097:                 actualNo=self.cdliRoot.getFileObjectLastVersion(obj).getVersionNumber()
        !          1098:             
        !          1099:             if actualNo==nummer:
        !          1100:                 return True , 0
        !          1101:             else:
        !          1102:                 return False, actualNo
        !          1103:         except:
        !          1104:             logging.error( """is actual: %s (%s %s)"""%(repr(obj),sys.exc_info()[0],sys.exc_info()[1]))
        !          1105:             logging.error("""         PARAMS: %s %s"""%(obj,nummer))
        !          1106:             return False, -1
        !          1107:     def isActualOld(self,obj):
1.4       dwinter  1108:         """teste ob im basket die aktuelle version ist"""
1.85      dwinter  1109:         try:
1.93      dwinter  1110:             #logging.debug("isActual:"+repr(obj))
1.85      dwinter  1111:             actualNo=obj[1].getLastVersion().getVersionNumber()
                   1112:             storedNo=obj[0].getVersionNumber()
                   1113:             
1.87      dwinter  1114:            
1.93      dwinter  1115:             #actualNo=self.getFileObjectLastVersion(obj.getId()).getVersionNumber()
1.85      dwinter  1116:                 
1.87      dwinter  1117:             #if len(founds)>0 and founds[0].getObject().aq_parent.getId()==".trash":
                   1118:             #    return False, -1
1.37      dwinter  1119:             
1.85      dwinter  1120:             if actualNo==storedNo:
                   1121:                 return True , 0
                   1122:             else:
                   1123:                 return False, actualNo
                   1124:         except:
1.93      dwinter  1125:             logging.error( """is actual: %s (%s %s)"""%(repr(obj),sys.exc_info()[0],sys.exc_info()[1]))
                   1126:     
1.12      dwinter  1127:             return False, -1
1.85      dwinter  1128:             
1.4       dwinter  1129:     def history(self):
                   1130:         """history"""  
                   1131: 
                   1132:         ext=self.ZopeFind(self.aq_parent,obj_ids=["history_template.html"])
                   1133:         if ext:
                   1134:             return getattr(self,ext[0][1].getId())()
                   1135:         
                   1136:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','BasketHistory')).__of__(self)
                   1137:         return pt()
                   1138:     
                   1139:     def getStorageFolderRoot(self):
                   1140:         """root des storage folders"""
                   1141:         return self.aq_parent.cdli_main
                   1142:     
                   1143:     def __init__(self,id,title,shortDescription="",comment=""):
                   1144:         """init a CDLIBasket"""
                   1145:         
                   1146:         self.id=id
                   1147:         self.title=title
                   1148:         self.shortDescription=shortDescription
                   1149:         self.comment=comment
                   1150:  
1.72      dwinter  1151:     def getActualUserName(self):
                   1152:         """get name of the actualuser"""
                   1153:        
                   1154:         return str(self.REQUEST['AUTHENTICATED_USER'])
                   1155:   
1.4       dwinter  1156:            
                   1157:     def getLastVersion(self):
                   1158:         """hole letzte version"""
1.39      dwinter  1159: 
                   1160:         ids=[]
                   1161:         idsTmp= self.objectIds()
                   1162:         for x in idsTmp:
                   1163:             try:
                   1164:                 ids.append(int(x))
                   1165:             except:
                   1166:                 pass
1.4       dwinter  1167:         ids.sort()
1.39      dwinter  1168:       
1.4       dwinter  1169:         if len(ids)==0:
                   1170:             return None
                   1171:         else:    
                   1172:             ob=getattr(self,str(ids[-1]))
1.39      dwinter  1173: 
                   1174:             
1.4       dwinter  1175:             return ob
                   1176:    
                   1177:     def getVersions(self):
                   1178:         """get versions"""
                   1179:         versions=self.ZopeFind(self,obj_metatypes=["CDLIBasketVersion"])
                   1180:         return versions
                   1181: 
                   1182:    
1.37      dwinter  1183:     def updateObjects(self,ids,RESPONSE=None,REQUEST=None):
                   1184:         """update ids, ids not in the basket the add"""
                   1185:         if type(ids) is not ListType:
                   1186:             ids=[ids]
                   1187:        
                   1188:         lastVersion=self.getLastVersion() 
1.39      dwinter  1189:         oldContent=lastVersion.content.getContent()
1.37      dwinter  1190:         newContent=[]
                   1191:         
                   1192:         #first copy the old
                   1193:         for obj in oldContent:
                   1194:             if obj[1].getId() not in ids:
                   1195:                 newContent.append(obj)
                   1196:         #now add the new
                   1197:                
                   1198:         for id in ids:
                   1199:             founds=self.CDLICatalog.search({'title':id})
                   1200: 
                   1201:             for found in founds:
                   1202:                 if found.getObject() not in oldContent:
                   1203:                     #TODO: was passiert wenn, man eine Object dazufŸgt, das schon da ist aber eine neuere version
                   1204:                     newContent.append((found.getObject().getLastVersion(),found.getObject()))
                   1205:         
                   1206: 
                   1207:         content=newContent 
                   1208:         user=self.getActualUserName()
                   1209:         
                   1210:         ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=newContent)
                   1211:         
1.38      dwinter  1212:         obj=self._getOb(ob.getId())
1.37      dwinter  1213:         if RESPONSE:
1.38      dwinter  1214:            
1.37      dwinter  1215:             RESPONSE.redirect(obj.absolute_url())
1.38      dwinter  1216:         
                   1217:         return obj
                   1218:     
1.72      dwinter  1219:     def addObjectsWithVersion(self,ids,deleteOld=None,username=None,catalog=None):
                   1220:         """generate a new version of the basket with objects added, 
                   1221:         hier wird jedoch nicht die letzte Version jedes Files hinzugefuegt, s
                   1222:         ondern ids is ein Tupel mit der Id (d.h. der p-number) und der Versionsnummer.
                   1223:         """
                   1224:         logging.info("add to basket (%s)"%(self.getId()))
                   1225:         lastVersion=self.getLastVersion()
                   1226:         
                   1227:         if not catalog:
                   1228:             catalog=self.CDLICatalog
                   1229:             
                   1230:         if lastVersion is None:
                   1231:             oldContent=[]
                   1232:         else:
                   1233:             oldContent=lastVersion.content.getContent()
                   1234: 
                   1235:         if deleteOld:
                   1236:             oldContent=[]
                   1237: 
                   1238:         newContent=[]
                   1239:         added=0
                   1240:        
                   1241:         for id,version in ids.iteritems():
                   1242:             logging.info("adding %s %s"%(id,version))
                   1243:             id=id.split(".")[0] # title nur die pnumber ohne atf
                   1244:            
                   1245:             try:
                   1246:                 founds=catalog.search({'title':id})
                   1247:             except:
                   1248:                 founds=[]
                   1249:             logging.info(" found %s "%(founds))
                   1250:             for found in founds:
                   1251:                 if found.getObject() not in oldContent:
                   1252:                  
                   1253:                     #TODO: was passiert wenn, man eine Object dazufŸgt, das schon da ist aber eine neuere version
                   1254:                     newContent.append((found.getObject().getVersions()[version-1][1],found.getObject()))
                   1255:                     added+=1
                   1256: 
                   1257:         content=oldContent+newContent
                   1258:         if not username:
                   1259:             logging.error("XXXXXXXXXXX %s"%repr(self))
                   1260:             user=self.getActualUserName()
                   1261:         else:
                   1262:             user = username
                   1263:             
                   1264:         ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=content)
                   1265:         logging.info("add to basket (%s) done"%(self.getId()))
                   1266:         return added
                   1267:     
                   1268:     
1.19      dwinter  1269:     def addObjects(self,ids,deleteOld=None,username=None):
1.4       dwinter  1270:         """generate a new version of the basket with objects added"""
1.83      dwinter  1271:         
                   1272:         def swap(x):
                   1273:             return (x[1],x[0])
                   1274:             
1.100     dwinter  1275:         logging.info("add to basket (%s)"%(repr(ids)))
1.65      dwinter  1276:         logging.info("add to basket (%s)"%(self.getId()))
1.4       dwinter  1277:         lastVersion=self.getLastVersion()
                   1278:         
                   1279:         if lastVersion is None:
                   1280:             oldContent=[]
                   1281:         else:
1.39      dwinter  1282:             oldContent=lastVersion.content.getContent()
1.4       dwinter  1283: 
                   1284:         if deleteOld:
                   1285:             oldContent=[]
                   1286: 
1.6       dwinter  1287:         added=0
1.83      dwinter  1288: #        for id in ids:
                   1289: #            logging.debug("adding:"+id)
                   1290: #            try:
                   1291: #                founds=self.CDLICatalog.search({'title':id})
                   1292: #            except:
                   1293: #                founds=[]
                   1294: #           
                   1295: #            for found in founds:
                   1296: #                if found.getObject() not in oldContent:
                   1297: #                    #TODO: was passiert wenn, man eine Object dazufŸgt, das schon da ist aber eine neuere version
                   1298: #                    newContent.append((found.getObject().getLastVersion(),found.getObject()))
                   1299: #                    added+=1
                   1300: 
1.85      dwinter  1301:         hash = md5.new(repr(makelist(ids))).hexdigest() # erzeuge hash als identification
1.83      dwinter  1302:         #logging.debug("JJJJJJJ:"+repr(self.makelist(ids)))
1.93      dwinter  1303:        
1.102   ! dwinter  1304:         retrieved = self.CDLICache.retrieve(hash)
        !          1305:         if retrieved:
        !          1306:             newContent=Set(map(swap,retrieved))
1.83      dwinter  1307:         else:
1.102   ! dwinter  1308:             newContent=Set([(self.getFileObjectLastVersion(x),self.getFileObject(x)) for x in ids])             
        !          1309:        
        !          1310:      
1.83      dwinter  1311:         
1.100     dwinter  1312:         #remove all Elements which are not stored
                   1313:         if (None,None) in newContent:   
                   1314:             newContent.remove((None,None))
1.83      dwinter  1315:         content=Set(oldContent).union(newContent)
                   1316:         added = len(content)-len(oldContent)
1.19      dwinter  1317:         if not username:
                   1318:             user=self.getActualUserName()
                   1319:         else:
                   1320:             user = username
1.83      dwinter  1321:         
                   1322:         #logging.debug("content:"+repr(list(content)))
                   1323:         ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=list(content))
1.65      dwinter  1324:         logging.info("add to basket (%s) done"%(self.getId()))
1.6       dwinter  1325:         return added
1.4       dwinter  1326:     
1.51      dwinter  1327:     
                   1328:                 
1.72      dwinter  1329:     def getContent(self):
                   1330:         """print content"""
                   1331:         ret=[]
                   1332:         
                   1333:         lv=self.getLastVersion()
1.102   ! dwinter  1334:         #for obj in lv.content.getContent():
1.93      dwinter  1335:             #logging.info("XXXXXXXXXX %s"%repr(obj))
1.102   ! dwinter  1336:         #    ret.append((obj[1].getId(),obj[0].versionNumber))
1.72      dwinter  1337:             
1.102   ! dwinter  1338:         return lv
1.72      dwinter  1339:         
1.49      dwinter  1340:     def getContentIds(self):
                   1341:         """print basket content"""
                   1342:         ret=[]
                   1343:         lv=self.getLastVersion()
1.51      dwinter  1344:         for obj in lv.content.getContent():
1.49      dwinter  1345:             ret.append((obj[0].getId(),obj[1].getId()))
                   1346:         
                   1347:         
                   1348:         return lv.getComment(),lv.getUser(),lv.getTime(),ret
                   1349: 
1.37      dwinter  1350:     def changeBasket(self,ids,submit,RESPONSE=None,REQUEST=None):
                   1351:         """change a basket"""
                   1352:         if submit=="update":
                   1353:             return self.updateObjects(ids,RESPONSE=RESPONSE,REQUEST=REQUEST)
                   1354:         elif submit=="delete":
                   1355:             return self.deleteObjects(ids,RESPONSE=RESPONSE,REQUEST=REQUEST)
                   1356:             
1.12      dwinter  1357:     def deleteObjects(self,ids,RESPONSE=None,REQUEST=None):
1.4       dwinter  1358:         """delete objects"""
1.12      dwinter  1359:         
                   1360:         if type(ids) is not ListType:
                   1361:             ids=[ids]
                   1362:        
                   1363:         lastVersion=self.getLastVersion() 
1.39      dwinter  1364:         oldContent=lastVersion.content.getContent()
1.12      dwinter  1365:         newContent=[]
                   1366:         for obj in oldContent:
                   1367:             if obj[1].getId() not in ids:
                   1368:                 newContent.append(obj)
                   1369:         
                   1370:                 
                   1371:         user=self.getActualUserName()
                   1372:         
                   1373:         ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=newContent)
                   1374:         
                   1375:         if RESPONSE:
                   1376:             obj=self._getOb(ob.getId())
                   1377:             RESPONSE.redirect(obj.absolute_url())
1.4       dwinter  1378:         
                   1379: def manage_addCDLIBasketForm(self):
                   1380:     """add the CDLIBasketContainer form"""
                   1381:     pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addCDLIBasket.zpt')).__of__(self)
                   1382:     return pt()
                   1383: 
                   1384: def manage_addCDLIBasket(self,title,shortDescription="",comment="",RESPONSE=None):
                   1385:     """add the basket"""
                   1386:     
                   1387:     id=str(self.getNewId())
                   1388:     
                   1389:     ob=CDLIBasket(id,title,shortDescription,comment)
                   1390:     
                   1391:     self._setObject(id, ob)
                   1392:     
                   1393:     if RESPONSE is not None:
                   1394:         RESPONSE.redirect('manage_main')
                   1395:     else:
                   1396:         return ob
                   1397: 
1.39      dwinter  1398: class CDLIBasketVersion(Implicit,Persistent,Folder):
1.4       dwinter  1399:     """version of a basket"""
                   1400:     
                   1401:     meta_type="CDLIBasketVersion"
1.32      dwinter  1402:     security=ClassSecurityInfo()
1.4       dwinter  1403:     
1.39      dwinter  1404:     def updateBasket(self):
                   1405:         """update"""
                   1406:         try:
                   1407:             self._setObject('content',BasketContent(self.basketContent))
                   1408:         except:
                   1409:             try:
                   1410:                 if len(self.basketContent)>0:
                   1411:                     self.content.setContent(self.basketContent)
                   1412:             except:
                   1413:                 print "error",self.getId(),self.aq_parent.getId()
                   1414:         self.basketContent=[]
                   1415: 
                   1416:         
1.37      dwinter  1417:     def containsNonActualFiles(self):
                   1418:         """returns True if basket contains one or more non current files"""
                   1419:         
                   1420:         objs=self.getContent()
                   1421:         for obj in objs:
1.102   ! dwinter  1422:             if not self.isActual(obj[0],obj[1])[0]:
1.37      dwinter  1423:                 return True
                   1424:         return False
                   1425:     
1.72      dwinter  1426:     def downloadListOfPnumbers(self):
                   1427:         """download pnumbers of the basket as list"""
                   1428:         
                   1429:         basket_name=self.aq_parent.title
                   1430:         
                   1431:         ids=self.getContent() # get the list of objects
                   1432:         logging.error(ids)
                   1433:         ret="\n".join([x[1].getId().split(".")[0] for x in ids])
                   1434:         
                   1435:         self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename="%s.txt" """%basket_name)
                   1436:         self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
                   1437:         length=len(ret)
                   1438:         self.REQUEST.RESPONSE.setHeader("Content-Length",length)
                   1439:         self.REQUEST.RESPONSE.write(ret)    
                   1440:         
1.77      dwinter  1441:     security.declareProtected('manage','downloadObjectsAsOneFile')
1.37      dwinter  1442:     def downloadObjectsAsOneFile(self,lock=None,procedure=None,REQUEST=None,check="yes",current="no"):
1.4       dwinter  1443:         """download all selected files in one file"""
1.93      dwinter  1444:         
1.46      dwinter  1445:         if self.temp_folder.downloadCounterBaskets > 10000:
                   1446:             return """I am sorry, currently the server has to many requests for downloads, please come back later!"""
1.45      dwinter  1447: 
                   1448: 
1.37      dwinter  1449:         if (check=="yes") and self.containsNonActualFiles():
                   1450:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadObjectAsOneFile_check.zpt')).__of__(self)
1.46      dwinter  1451:             
1.37      dwinter  1452:             return pt(lock=lock)
                   1453:             
1.46      dwinter  1454:         else:
                   1455:             
                   1456:             return self.downloadObjectsAsOneFileFinally(lock=lock,procedure=procedure,REQUEST=REQUEST,current="no")
                   1457:         
1.87      dwinter  1458:     def downloadObjectsAsOneFileFinally(self,lock=None,procedure=None,REQUEST=None,current="no",repeat=None):
1.46      dwinter  1459:         """print do the download"""
1.87      dwinter  1460:  
1.93      dwinter  1461:         
1.46      dwinter  1462:         ret=""
1.4       dwinter  1463:         lockedObjects={}
                   1464: 
1.87      dwinter  1465:            
1.93      dwinter  1466:     
1.4       dwinter  1467:         if lock:
1.87      dwinter  1468:             logging.debug("------lock:"+repr(lock))
1.4       dwinter  1469:             if str(self.REQUEST['AUTHENTICATED_USER'])=='Anonymous User':
1.87      dwinter  1470:                 
1.4       dwinter  1471:                 return "please login first"
                   1472: 
                   1473:             #check if a locked object exist in the basket.
                   1474:             lockedObjects={}
1.39      dwinter  1475:             for object in self.content.getContent():
1.102   ! dwinter  1476:                 obj=self.getFileObject(object[0])
        !          1477:                 if (not str(obj.lockedBy)=="") and (not (str(obj.lockedBy)==str(self.REQUEST['AUTHENTICATED_USER']))):
        !          1478:                     lockedObjects[obj.title]=repr(obj.lockedBy)
1.4       dwinter  1479:                    
                   1480:                     
                   1481:             keys=lockedObjects.keys()
                   1482:             
                   1483:             
                   1484:             if len(keys)>0 and (not procedure):
                   1485:                 self.REQUEST.SESSION['lockedObjects']=lockedObjects
                   1486:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','lockedObjects.zpt')).__of__(self)
1.45      dwinter  1487:                 
1.87      dwinter  1488:                
1.46      dwinter  1489:                 return pt()
1.4       dwinter  1490:          
                   1491:             elif not procedure: #keine fails gesperrt dann alle donwloaden
                   1492:                 procedure="downloadAll" 
                   1493:         
1.46      dwinter  1494:         
1.87      dwinter  1495:        
                   1496:        
                   1497:         threadName=repeat
                   1498:         if not threadName or threadName=="":
                   1499:             thread=DownloadBasketFinallyThread()
                   1500:             threadName=thread.getName()[0:]
                   1501: 
                   1502:             if (not hasattr(self,'_v_downloadBasket')):
                   1503:                                 self._v_downloadBasket={}
                   1504: 
                   1505: 
                   1506:             self._v_downloadBasket[threadName]=thread
                   1507:             logging.debug("dwonloadfinally:"+repr(self))
1.97      dwinter  1508: 
1.96      dwinter  1509:             if isinstance(self,CDLIBasketVersion):
                   1510:                 obj=self
                   1511:             else:
                   1512:                 obj=self.aq_parent
1.95      dwinter  1513:             logging.debug("dwonloadfinally2:"+repr(obj))
                   1514:             logging.debug("dwonloadfinally2:"+repr(obj.aq_parent))
                   1515: 
1.96      dwinter  1516:             obj2=obj.aq_parent
                   1517:             if not isinstance(obj2,CDLIBasket):
1.95      dwinter  1518:                 obj2=obj2.aq_parent
                   1519: 
                   1520:             basketID=obj2.getId()
                   1521:             versionNumber=obj.getId()
                   1522:             logging.debug("dwonloadfinally2:"+repr(basketID))
                   1523:             logging.debug("dwonloadfinally2:"+repr(versionNumber))
                   1524: 
1.97      dwinter  1525: 
1.88      dwinter  1526:             if lock:
                   1527:                 logging.debug("-----start locking")
                   1528:                 for object in self.content.getContent():
1.102   ! dwinter  1529:                          obj=self.ctx.getFileObject(object[0])
        !          1530:                          if obj.lockedBy =='':
        !          1531:                              obj.lockedBy=self.REQUEST['AUTHENTICATED_USER']
1.88      dwinter  1532:                 logging.debug("-----finished locking")
                   1533:                 
                   1534:                     #obj.lockedBy=user
                   1535:             self._v_downloadBasket[threadName].set(lock,procedure,self.REQUEST['AUTHENTICATED_USER'],current,basketID,versionNumber)
1.45      dwinter  1536: 
1.87      dwinter  1537:             self._v_downloadBasket[threadName].start()
1.4       dwinter  1538: 
1.87      dwinter  1539:             
                   1540:             
                   1541:             wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
                   1542: 
                   1543:             if wait_template:
                   1544:                 return wait_template[0][1]()
                   1545:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadBasketWait.zpt')).__of__(self)
                   1546: 
1.88      dwinter  1547:             return pt(txt=self.absolute_url()+'/downloadObjectsAsOneFileFinally',threadName=threadName,
                   1548:                                 counter=self._v_downloadBasket[threadName].getCounter(),
                   1549:                                 number=self._v_downloadBasket[threadName].getNumberOfFiles())
1.87      dwinter  1550:             #_v_xmltrans.run()
                   1551:         
                   1552:         else:
                   1553:             #recover thread, if lost
                   1554:             if not hasattr(self,'_v_downloadBasket'):
                   1555:                self._v_downloadBasket={}
                   1556:             if not self._v_downloadBasket.get(threadName,None):
                   1557:                  for thread in threading.enumerate():
                   1558:                          if threadName == thread.getName():
                   1559:                                        self._v_downloadBasket[threadName]=thread
                   1560:                                        
                   1561:             if self._v_downloadBasket.get(threadName,None) and (self._v_downloadBasket[threadName] is not None) and (not self._v_downloadBasket[threadName].end) :
                   1562: 
                   1563:                 wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
                   1564:                 if wait_template:
                   1565:                         return wait_template[0][1]()
1.83      dwinter  1566:                 
1.87      dwinter  1567:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadBasketWait.zpt')).__of__(self)
1.88      dwinter  1568:                 return pt(txt=self.absolute_url()+'/downloadObjectsAsOneFileFinally',threadName=threadName,
                   1569:                           counter=self._v_downloadBasket[threadName].getCounter(),
                   1570:                           number=self._v_downloadBasket[threadName].getNumberOfFiles())
1.87      dwinter  1571:             else:
                   1572:               
                   1573:              
                   1574:               logging.debug("FINISHED")
                   1575:               if not self._v_downloadBasket.get(threadName,None):
                   1576:                  for thread in threading.enumerate():
                   1577:                          if threadName == thread.getName():
                   1578:                                        self._v_downloadBasket[threadName]=thread
                   1579:                                        
                   1580:               #files = self._v_downloadBasket[threadName].result
                   1581:               files=self.basketContainer.resultHash[threadName]
1.90      dwinter  1582:               lockedFiles=self.basketContainer.resultLockedHash[threadName]
1.92      dwinter  1583:      
1.87      dwinter  1584:              # fh=file("/var/tmp/test")
                   1585:               #ret =fh.read()
                   1586:          
                   1587:               if (not isinstance(self.aq_parent,CDLIBasket)):
                   1588:                   basket_name=self.aq_parent.aq_parent.title+"_V"+self.getId()
                   1589:               else:
                   1590:                   basket_name=self.aq_parent.title+"_V"+self.getId()
1.86      dwinter  1591:         
                   1592:         
                   1593:     
1.87      dwinter  1594:                   #write basketname to header of atf file
                   1595:               
1.45      dwinter  1596: 
1.87      dwinter  1597:               self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename="%s.atf" """%basket_name)
                   1598:               self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
                   1599:               #length=len(ret)
                   1600:               #self.REQUEST.RESPONSE.setHeader("Content-Length",length)
1.90      dwinter  1601:         
1.87      dwinter  1602:               ret="#basket: %s\n"%basket_name
1.90      dwinter  1603:               self.REQUEST.RESPONSE.write(ret) 
                   1604:                  
1.87      dwinter  1605:               for fileName in files:
1.102   ! dwinter  1606:                 logging.debug("download: %s"%fileName)
1.91      dwinter  1607:                 try:
1.87      dwinter  1608:                   self.REQUEST.RESPONSE.write(file(fileName).read())
1.91      dwinter  1609:                 except:
                   1610:                   logging.error("downloadasonefile: cannot read %s"%fileName)
1.90      dwinter  1611:                   
                   1612:             
                   1613:               self.REQUEST.RESPONSE.write("\n# locked files\n")
                   1614:               for fileName in lockedFiles:
1.92      dwinter  1615:                   self.REQUEST.RESPONSE.write("#  %s by %s\n"%fileName)
1.90      dwinter  1616:               
                   1617:               self.REQUEST.RESPONSE.write("# locked files end\n")
                   1618:               
1.87      dwinter  1619:               del self.basketContainer.resultHash[threadName]
1.90      dwinter  1620:               del self.basketContainer.resultLockedHash[threadName]
1.87      dwinter  1621:              
1.4       dwinter  1622:     def numberOfItems(self):
                   1623:         """return anzahl der elemente im basket"""
1.39      dwinter  1624:         return self.content.numberOfItems()
1.4       dwinter  1625:     
                   1626:     def getTime(self):
                   1627:         """getTime"""
                   1628:         #return self.bobobase_modification_time().ISO()
                   1629:       
                   1630:         if hasattr(self,'time'):
                   1631:             return time.strftime("%Y-%m-%d %H:%M:%S",self.time)
                   1632:         elif hasattr(self,'timefixed'):
                   1633:             return self.timefixed
                   1634:         else:
                   1635:             setattr(self,'timefixed',self.bobobase_modification_time().ISO())
                   1636:             return self.bobobase_modification_time().ISO()
                   1637:     
                   1638:     def getContent(self):
                   1639:         """get Basket Content"""
1.102   ! dwinter  1640:         logging.debug("retrieving content A")
        !          1641:         cnt = self.content
        !          1642:         logging.debug("retrieving content: obj %s"%cnt)
        !          1643:         tmp = self.content.getContent()
        !          1644:         logging.debug("got content")
        !          1645:         return tmp
1.4       dwinter  1646: 
                   1647:     
                   1648:     def __init__(self,id,user,comment="",basketContent=[]):
                   1649:         """ init a basket version"""
                   1650:         self.id=id
1.74      dwinter  1651:         self.comment=comment
1.39      dwinter  1652:         self._setObject('content',BasketContent(basketContent))
                   1653:         #self.basketContent=basketContent[0:]a
1.4       dwinter  1654:         self.user=user
                   1655:         self.time=time.localtime()
                   1656:         
                   1657:     def getUser(self):
                   1658:         """get user"""
                   1659:         return self.user
                   1660:     
                   1661:     def getComment(self):
                   1662:         """get Comment"""
                   1663:         return self.comment
                   1664:  
1.77      dwinter  1665:     security.declareProtected('manage','index_html')
1.4       dwinter  1666:     def index_html(self):
                   1667:             """view the basket"""
1.102   ! dwinter  1668:             logging.debug("start index_html - Basket version")    
1.37      dwinter  1669:             if self.REQUEST.get('change',False):
1.38      dwinter  1670:                     ob=self.aq_parent.updateObjects(self.REQUEST['change'])
                   1671:                    
                   1672:                     self.REQUEST.RESPONSE.redirect(ob.absolute_url())#go to new basket, because changing generates a new basket
1.102   ! dwinter  1673:             logging.debug("start index_html - Basket version:template")    
1.4       dwinter  1674:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','BasketVersionMain.zpt')).__of__(self)
                   1675:             return pt()
                   1676:      
                   1677:     def getObjUrl(self,result):
                   1678:         """getUrl of the version of the object"""
1.102   ! dwinter  1679:       
        !          1680:         founds=self.CDLICatalog.search({'title':result})
1.4       dwinter  1681:         if len(founds)>0:
1.12      dwinter  1682:              return founds[0].getObject().getLastVersion().absolute_url()
1.4       dwinter  1683:          
                   1684:         else: #assume version number
1.102   ! dwinter  1685:             splitted=result.split("_")
1.9       dwinter  1686:             founds=self.CDLICatalog.search({'title':splitted[1]})        
1.102   ! dwinter  1687:             return founds[0].getObject().getLastVersion().absolute_url()+'/'+result
1.4       dwinter  1688:    
                   1689: def manage_addCDLIBasketVersion(self,user,comment="",basketContent=[],RESPONSE=None):
                   1690:     """add a version"""
                   1691:     
                   1692:     #check for already existing versions
                   1693:  
                   1694:     lastVersion=self.getLastVersion()
                   1695:     if lastVersion is None:
                   1696:         newId=str(1)
                   1697:     else:
                   1698:         newId=str(int(lastVersion.getId())+1)
                   1699:     
                   1700:     ob=CDLIBasketVersion(newId,user,comment,basketContent)
                   1701:     
                   1702:     self._setObject(newId, ob)
                   1703:     
                   1704:     if RESPONSE is not None:
                   1705:         RESPONSE.redirect('manage_main')
                   1706:     else:
                   1707:         return ob
                   1708:     
1.46      dwinter  1709: class CDLIFileObject(CatalogAware,extVersionedFileObject):
1.1       dwinter  1710:     """CDLI file object"""
                   1711:     
                   1712:     meta_type="CDLI File Object"
1.25      dwinter  1713:     default_catalog='CDLIObjectsCatalog'
1.1       dwinter  1714:     
1.12      dwinter  1715:     security=ClassSecurityInfo()
                   1716:     
1.78      dwinter  1717:     security.declareProtected('manage','index_html')
1.81      casties  1718: 
                   1719:     security.declarePublic('view')
                   1720:     view = PageTemplateFile('zpt/viewCDLIFile.zpt', globals())
                   1721: 
                   1722:     security.declarePublic('editATF')
                   1723:     editATF = PageTemplateFile('zpt/editATFFile.zpt', globals())
                   1724: 
1.28      dwinter  1725:     def PrincipiaSearchSource(self):
                   1726:            """Return cataloguable key for ourselves."""
                   1727:            return str(self)
                   1728:        
1.89      dwinter  1729:     def setAuthor(self, author):
                   1730:         """change the author"""
                   1731:         self.author = author
                   1732:        
1.26      dwinter  1733:     def makeThisVersionCurrent_html(self):
1.85      dwinter  1734:         """form for mthis version current"""
1.26      dwinter  1735:         
                   1736:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','makeThisVersionCurrent.zpt')).__of__(self)
                   1737:         return pt()                 
1.81      casties  1738: 
                   1739:     security.declarePublic('makeThisVersionCurrent')
1.27      dwinter  1740:     def makeThisVersionCurrent(self,comment,author,RESPONSE=None):
1.26      dwinter  1741:         """copy this version to current"""
                   1742:         parent=self.aq_parent
1.81      casties  1743:         parent.manage_addVersionedFileObject(id=None,vC=comment,author=author,file=self.getData(),RESPONSE=RESPONSE)
                   1744:         #newversion=parent.manage_addCDLIFileObject('',comment,author)
                   1745:         #newversion.manage_upload(self.getData())
1.27      dwinter  1746:                                         
1.81      casties  1747:         #if RESPONSE is not None:
                   1748:         #    RESPONSE.redirect(self.aq_parent.absolute_url()+'/history')
1.27      dwinter  1749: 
1.26      dwinter  1750:         return True
                   1751:     
1.52      dwinter  1752:     def getFormattedData(self):
                   1753:         """fromat text"""
                   1754:         data=self.getData()
1.70      dwinter  1755: #        return re.sub("\s\#lem"," #lem",data) #remove return vor #lem
                   1756:         return re.sub("#lem","       #lem",data) #remove return vor #lem
1.52      dwinter  1757:         
1.1       dwinter  1758:     
1.40      dwinter  1759:     security.declarePublic('getPNumber')
                   1760:     def getPNumber(self):
1.46      dwinter  1761:         """get the pnumber"""
                   1762:         try:
1.49      dwinter  1763:                 txt=re.match("&[Pp](\d*)\s*=([^\r\n]*)",self.getData()[0:])
1.40      dwinter  1764:         except:
1.49      dwinter  1765:                 txt=self.getData()[0:]
1.40      dwinter  1766:                 
                   1767:                 return "ERROR"
                   1768:         try:
                   1769:             return "P"+txt.group(1)
                   1770:         except:
                   1771:             return "ERROR"
                   1772: 
1.12      dwinter  1773:     security.declarePublic('getDesignation')
                   1774:     def getDesignation(self):
                   1775:         """get the designation out of the file"""
1.16      dwinter  1776:         try:
1.46      dwinter  1777:                 txt=re.match("&[Pp](\d*)\s*=([^\r\n]*)",self.getData()[0:])
1.13      dwinter  1778:         except:
1.46      dwinter  1779:                 txt=self.getData()[0:]
1.16      dwinter  1780:                 
                   1781:                 return "ERROR"
1.12      dwinter  1782:         try:
                   1783:             return txt.group(2)
                   1784:         except:
                   1785:             return "ERROR"
1.81      casties  1786: 
1.12      dwinter  1787:         
1.1       dwinter  1788: manage_addCDLIFileObjectForm=DTMLFile('dtml/fileAdd', globals(),Kind='CDLIFileObject',kind='CDLIFileObject', version='1')
                   1789: 
1.81      casties  1790: def manage_addCDLIFileObject(self,id,vC='',author='', file='',title='',versionNumber=0,
                   1791:                              precondition='', content_type='',
1.48      dwinter  1792:                              from_tmp=False,REQUEST=None):
1.1       dwinter  1793:     """Add a new File object.
                   1794:     Creates a new File object 'id' with the contents of 'file'"""
1.48      dwinter  1795:  
1.1       dwinter  1796:     id=str(id)
                   1797:     title=str(title)
                   1798:     content_type=str(content_type)
                   1799:     precondition=str(precondition)
                   1800:     
                   1801:     id, title = cookId(id, title, file)
                   1802: 
                   1803:     self=self.this()
                   1804: 
                   1805:     # First, we create the file without data:
1.81      casties  1806:     self._setObject(id, CDLIFileObject(id,title,versionNumber=versionNumber,versionComment=vC,time=time.localtime(),author=author))
1.80      casties  1807:     fob = self._getOb(id)
1.45      dwinter  1808:     
1.1       dwinter  1809:     # Now we "upload" the data.  By doing this in two steps, we
                   1810:     # can use a database trick to make the upload more efficient.
1.48      dwinter  1811: 
                   1812:     if file and not from_tmp:
1.80      casties  1813:         fob.manage_upload(file)
1.48      dwinter  1814:     elif file and from_tmp:
1.81      casties  1815:         fob.manage_file_upload(file) # manage_upload_from_tmp doesn't exist in ExtFile2
                   1816:     #    fob.manage_upload_from_tmp(file) # manage_upload_from_tmp doesn't exist in ExtFile2
1.1       dwinter  1817:     if content_type:
1.80      casties  1818:         fob.content_type=content_type
1.1       dwinter  1819: 
1.81      casties  1820:     #logging.debug("manage_add: lastversion=%s"%self.getData())
                   1821:     logging.debug("reindex1: %s in %s"%(repr(self),repr(self.default_catalog)))
1.45      dwinter  1822:     self.reindex_object()
1.81      casties  1823:     #logging.debug("manage_add: fob_data=%s"%fob.getData())
1.80      casties  1824:     logging.debug("reindex2: %s in %s"%(repr(fob), repr(fob.default_catalog)))
1.81      casties  1825:     fob.index_object()
1.49      dwinter  1826: 
1.85      dwinter  1827:     self.CDLIRoot.updateOrAddToFileBTree(ob)
1.1       dwinter  1828:     if REQUEST is not None:
                   1829:         REQUEST['RESPONSE'].redirect(self.absolute_url()+'/manage_main')
1.3       dwinter  1830:     
1.80      casties  1831: 
1.46      dwinter  1832: class CDLIFile(extVersionedFile,CatalogAware):
1.3       dwinter  1833:     """CDLI file"""
                   1834:     
1.77      dwinter  1835:     security=ClassSecurityInfo()
1.3       dwinter  1836:     meta_type="CDLI file"
1.81      casties  1837:     content_meta_type = ["CDLI File Object"]
                   1838:     
1.3       dwinter  1839:     default_catalog='CDLICatalog'
1.81      casties  1840:     
1.78      dwinter  1841:     security.declareProtected('manage','index_html')
1.81      casties  1842:     
1.51      dwinter  1843:     def getLastVersionData(self):
                   1844:         """get last version data"""
1.81      casties  1845:         return self.getData()
1.51      dwinter  1846: 
1.52      dwinter  1847:     def getLastVersionFormattedData(self):
                   1848:         """get last version data"""
1.81      casties  1849:         return self.getContentObject().getFormattedData()
                   1850: 
                   1851:     def getTextId(self):
                   1852:         """returns P-number of text"""
                   1853:         # assuming that its the beginning of the title
                   1854:         return self.title[:7]
1.52      dwinter  1855: 
1.51      dwinter  1856:     #security.declarePublic('history')
1.26      dwinter  1857:     def history(self):
                   1858:         """history"""  
                   1859: 
                   1860:         ext=self.ZopeFind(self.aq_parent,obj_ids=["history_template.html"])
                   1861:         if ext:
                   1862:             return getattr(self,ext[0][1].getId())()
                   1863:         
                   1864:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','versionHistory')).__of__(self)
                   1865:         return pt()
                   1866: 
                   1867: 
1.44      dwinter  1868:     def getBasketFromId(self,basketid, context=None):
                   1869:         """get basket from id"""
                   1870: 
                   1871:         if not context:
                   1872:             context=self
                   1873:             
                   1874:         for basket in self.ZopeFind(context,obj_metatypes=["CDLIBasket"]):
                   1875:             if basket[0]==basketid:
                   1876:                 return basket[1]
                   1877:         else:
                   1878:             None
                   1879: 
1.12      dwinter  1880:  
1.8       dwinter  1881:     def isContainedInBaskets(self,context=None):
                   1882:         """check is this file is part of any basket
                   1883:         @param context: (optional) necessessary if CDLIBasketCatalog is not an (inherited) attribute of self, context.CDLIBasketCatalog
                   1884:                         has to exist.
                   1885:         """
                   1886: 
                   1887:         if not context:
                   1888:             context=self
1.12      dwinter  1889:         
                   1890:         ret=[]
                   1891:         for x in context.CDLIBasketCatalog.search({'getFileNamesInLastVersion':self.getId()}):
                   1892:             #if the basket x is deleted it seemes to be that x is sometimes still in the Catalog, why?
                   1893:             try:
                   1894:                 ret.append(x.getObject())
                   1895:             except:
                   1896:                 pass
                   1897:         return ret
                   1898:         #return [x.getObject() for x in context.CDLIBasketCatalog.search({'getFileNamesInLastVersion':self.getId()})]
1.5       dwinter  1899:         
                   1900:         
1.81      casties  1901:     def _newContentObject(self, id, title='', versionNumber=0, versionComment=None, time=None, author=None):
                   1902:         """factory for content objects. to be overridden in derived classes."""
                   1903:         logging.debug("_newContentObject(CDLI)")
                   1904:         return CDLIFileObject(id,title,versionNumber=versionNumber,versionComment=versionComment,time=time,author=author)
                   1905: 
                   1906: 
1.5       dwinter  1907:     def addCDLIFileObjectForm(self):
                   1908:         """add a new version"""
                   1909:         
                   1910:         if str(self.REQUEST['AUTHENTICATED_USER']) in ["Anonymous User"]:
                   1911:             return "please login first"
                   1912:         if (self.lockedBy==self.REQUEST['AUTHENTICATED_USER']) or (self.lockedBy==''):
                   1913:             out=DTMLFile('dtml/fileAdd', globals(),Kind='CDLIFileObject',kind='CDLIFileObject',version=self.getVersion()).__of__(self)
                   1914:             return out()
                   1915:         else:
                   1916:             return "Sorry file is locked by somebody else"
                   1917:         
1.37      dwinter  1918:     def manage_addCDLIFileObject(self,id,vC,author,
                   1919:                                  file='',title='',
                   1920:                                  precondition='', 
                   1921:                                  content_type='',
                   1922:                                  changeName='no',newName='', 
1.48      dwinter  1923:                                  come_from=None,
                   1924:                                  from_tmp=False,RESPONSE=None):
1.3       dwinter  1925:         """add"""
1.48      dwinter  1926:       
1.3       dwinter  1927:         try: #TODO: der ganze vC unsinn muss ueberarbeitet werden
                   1928:             vC=self.REQUEST['vC']
                   1929:         except:
                   1930:             pass
                   1931:         
1.81      casties  1932:         ob = self.addContentObject(id, vC, author, file, title, changeName=changeName, newName=newName, from_tmp=from_tmp,
                   1933:                                    precondition=precondition, content_type=content_type)
1.3       dwinter  1934: 
1.22      dwinter  1935:         try:
1.81      casties  1936:             #FIXME: wozu ist das gut?
                   1937:             self.REQUEST.SESSION['objID_parent']=self.getId()
1.22      dwinter  1938:         except:
1.81      casties  1939:             pass
1.37      dwinter  1940:   
1.85      dwinter  1941:         #self.cdliRoot.updateOrAddToFileBTree(self)# now update the object in the cache
                   1942:       
                   1943:         
1.3       dwinter  1944:         if RESPONSE:
1.81      casties  1945:             if ob.getSize()==0:
                   1946:                 self.REQUEST.SESSION['objID']=ob.getId()
1.3       dwinter  1947:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','errorUploadFile')).__of__(self)
                   1948:                 return pt()
                   1949:             else:
1.37      dwinter  1950:                 if come_from and (come_from!=""):
1.81      casties  1951:                     RESPONSE.redirect(come_from+"?change="+self.getId())
1.37      dwinter  1952:                 else:
                   1953:                     RESPONSE.redirect(self.REQUEST['URL2']+'?uploaded=%s'%self.title)
1.3       dwinter  1954:         else:
1.81      casties  1955:             return ob
1.3       dwinter  1956:         
                   1957:         
                   1958: def manage_addCDLIFileForm(self):
                   1959:     """interface for adding the OSAS_root"""
                   1960:     pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addCDLIFile.zpt')).__of__(self)
                   1961:     return pt()
                   1962: 
                   1963: def manage_addCDLIFile(self,id,title,lockedBy, author=None, RESPONSE=None):
                   1964:     """add the OSAS_root"""
                   1965:     newObj=CDLIFile(id,title,lockedBy,author)
1.22      dwinter  1966:                                         
                   1967:     tryToggle=True
                   1968:     tryCount=0
                   1969: 
                   1970:     self._setObject(id,newObj)                  
1.45      dwinter  1971:     getattr(self,id).reindex_object()
1.22      dwinter  1972:         
1.3       dwinter  1973:     if RESPONSE is not None:
                   1974:         RESPONSE.redirect('manage_main')
                   1975: 
1.81      casties  1976: 
1.69      dwinter  1977: def checkUTF8(data):
                   1978:     """check utf 8"""
                   1979:     try:
                   1980:         data.encode('utf-8')
                   1981:         return True
                   1982:     except:
                   1983:         return False
                   1984:     
1.1       dwinter  1985: 
1.45      dwinter  1986: def checkFile(filename,data,folder):
                   1987:     """check the files"""
                   1988:     # first check the file name
                   1989:     fn=filename.split(".") # no extension
1.48      dwinter  1990: 
1.45      dwinter  1991:     if not fn[0][0]=="P":
1.46      dwinter  1992:         return False,"P missing in the filename"
1.45      dwinter  1993:     elif len(fn[0])!=7:
1.46      dwinter  1994:         return False,"P number has not the right length 6"
1.69      dwinter  1995:     elif not checkUTF8(data):
                   1996:         return False,"not utf-8"
1.45      dwinter  1997:     else:
1.69      dwinter  1998:         return True,""
                   1999:     
1.45      dwinter  2000:     
1.25      dwinter  2001: def splitatf(fh,dir=None,ext=None):
1.2       dwinter  2002:     """split it"""
1.4       dwinter  2003:     ret=None
1.2       dwinter  2004:     nf=None
1.25      dwinter  2005:     i=0
1.49      dwinter  2006: 
1.81      casties  2007:     #ROC: why split \n first and then \r???
1.73      dwinter  2008:     if (type(fh) is StringType) or (type(fh) is UnicodeType):
                   2009:         iter=fh.split("\n")
                   2010:     else:
                   2011:         iter=fh.readlines()
                   2012:         
                   2013:     for lineTmp in iter:
1.66      dwinter  2014:         lineTmp=lineTmp.replace(codecs.BOM_UTF8,'') # make sure that all BOM are removed..
                   2015:         for line in lineTmp.split("\r"):
                   2016:             #logging.log("Deal with: %s"%line)
                   2017:             if ext:
                   2018:                 i+=1
                   2019:                 if (i%100)==0:
                   2020:                     ext.result+="."
                   2021:                 if i==10000:
                   2022:                     i=0
                   2023:                     ext.result+="<br>"
                   2024:             #check if basket name is in the first line
                   2025:             if line.find("#atf basket")>=0: #old convention
                   2026:                 ret=line.replace('#atf basket ','')
                   2027:                 ret=ret.split('_')[0]
                   2028:             elif line.find("#basket:")>=0: #new convention
                   2029:                 ret=line.replace('#basket: ','')
                   2030:                 ret=ret.split('_')[0]
                   2031: 
                   2032:             else:
                   2033:                 if (len(line.lstrip())>0) and (line.lstrip()[0]=="&"): #newfile
                   2034:                     if nf:
                   2035:                         nf.close() #close last file
                   2036: 
1.49      dwinter  2037: 
1.66      dwinter  2038:                     filename=line[1:].split("=")[0].rstrip()+".atf"
                   2039:                     if dir:
                   2040:                         filename=os.path.join(dir,filename)
                   2041:                     nf=file(filename,"w")
                   2042:                     logging.info("open %s"%filename)
                   2043:                 if nf:    
                   2044:                     nf.write(line.replace("\n","")+"\n")
                   2045: 
                   2046:     try:        
                   2047:         nf.close()
1.61      dwinter  2048:     except:
1.66      dwinter  2049:         pass
1.73      dwinter  2050:     
                   2051:     if not((type(fh) is StringType) or (type(fh) is UnicodeType)):
                   2052:         fh.close()
1.5       dwinter  2053:     return ret,len(os.listdir(dir))
1.4       dwinter  2054: 
1.19      dwinter  2055: 
1.46      dwinter  2056: class CDLIFileFolder(extVersionedFileFolder):
1.4       dwinter  2057:     """CDLI File Folder"""
1.1       dwinter  2058:     
1.19      dwinter  2059:     security=ClassSecurityInfo()
1.1       dwinter  2060:     meta_type="CDLI Folder"
1.81      casties  2061:     file_meta_type=['CDLI file']
                   2062:     folder_meta_type=['CDLI Folder']
                   2063: 
                   2064:     file_catalog='CDLICatalog'
                   2065: 
1.45      dwinter  2066:     #downloadCounter=0 # counts how many download for all files currently run, be mehr als 5 wird verweigert.
1.24      dwinter  2067:     tmpStore2={}
1.81      casties  2068: 
                   2069:     def _newVersionedFile(self, id, title='', lockedBy=None, author=None):
                   2070:         """factory for versioned files. to be overridden in derived classes."""
                   2071:         logging.debug("_newVersionedFile(CDLI)")
                   2072:         return CDLIFile(id, title, lockedBy=lockedBy, author=author)
                   2073: 
1.19      dwinter  2074:     def setTemp(self,name,value):
                   2075:         """set tmp"""
                   2076: 
                   2077:         setattr(self,name,value)
                   2078:                                         
1.81      casties  2079:     deleteFileForm = PageTemplateFile("zpt/doDeleteFile", globals())
1.19      dwinter  2080:                                        
1.81      casties  2081:     def delete(self,ids,REQUEST=None):
                   2082:         """delete these files"""
1.12      dwinter  2083:         if type(ids) is not ListType:
                   2084:             ids=[ids]
1.81      casties  2085: 
                   2086:         self.manage_delObjects(ids)
1.12      dwinter  2087:         
1.81      casties  2088:         if REQUEST is not None:
                   2089:             return self.index_html()
                   2090: 
                   2091: 
1.4       dwinter  2092:     def getVersionNumbersFromIds(self,ids):
                   2093:         """get the numbers of the current versions of documents described by their ids"""
                   2094:         
                   2095:         ret=[]
                   2096:         searchStr=" OR ".join(ids)
                   2097:         
1.9       dwinter  2098:         founds=self.CDLICatalog.search({'title':searchStr})
1.4       dwinter  2099:         
                   2100:         for found in founds:
1.81      casties  2101:             lastVersion=found.getObject().getContentObject()
1.4       dwinter  2102:             ret.append((found.getId,lastVersion))
                   2103:         
                   2104:         return ret
                   2105:     
1.67      dwinter  2106:     def getFile(self,fn):
                   2107:         """get the content of the file fn"""
1.81      casties  2108:         logging.debug("getFile: %s"%repr(fn))
                   2109:         if not self.hasObject(fn):
                   2110:             # search deeper
                   2111:             founds=getattr(self, self.file_catalog).search({'textid':fn})
                   2112:             if founds:
                   2113:                 obj=founds[0].getObject().getContentObject()
                   2114:             else:
                   2115:                 return "" 
1.67      dwinter  2116:         else:
1.81      casties  2117:             obj = self[fn].getContentObject()
1.68      dwinter  2118: 
1.81      casties  2119:         return obj.getData()[0:] 
                   2120:  
1.67      dwinter  2121:     
1.14      dwinter  2122:     def checkCatalog(self,fn):
                   2123:         """check if fn is in the catalog"""
1.19      dwinter  2124:         #TODO add checkCatalog
1.14      dwinter  2125:         
1.19      dwinter  2126:                                    
1.45      dwinter  2127:     def findObjectsFromListWithVersion(self,list,author=None):
1.26      dwinter  2128:         """find objects from a list with versions
                   2129:         @param list: list of tuples  (cdliFile,version)
                   2130:         """
                   2131:         #self.REQUEST.SESSION['fileIds']=list#store fieldIds in session for further usage
                   2132:         #self.REQUEST.SESSION['searchList']=self.REQUEST.SESSION['fileIds']
                   2133:         
                   2134:         pt=getattr(self,'filelistVersioned.html')
                   2135:             
1.45      dwinter  2136:         return pt(search=list,author=author)
1.26      dwinter  2137:     
                   2138:     
1.67      dwinter  2139:     def getAllPNumbers(self):
                   2140:         """get a list of all files (resp their p-numbers) stored"""
                   2141:         
                   2142:         ret=[x.getId for x in  self.CDLICatalog()]
                   2143:      
                   2144:         return ret
                   2145:     
1.83      dwinter  2146:     def expandFile(self,fileId,fileTree):
                   2147:         """wildcard in fileID suche alle Treffer"""
                   2148:         founds=self.CDLICatalog({'title':fileId})
                   2149:         for found in founds:
                   2150:             fileTree.add(found.getId)
                   2151:             logging.debug("ADDD:"+found.getId)
                   2152:          
1.85      dwinter  2153:     def findObjectsFromList(self,enterList=None,display=False,start=None,upload=None,list=None,basketName=None,numberOfObjects=None,RESPONSE=None,REQUEST=None,returnHash=False,hash=None):
1.1       dwinter  2154:         """findObjectsFromList (, TAB oder LINE separated)"""
1.15      dwinter  2155:                                        
1.83      dwinter  2156:         logging.debug("start: findObjectsFromList")
1.85      dwinter  2157:         #logging.debug("start: findObjectsFromList"+repr(list))
                   2158:         
                   2159:             
1.6       dwinter  2160:         if upload: # list from file upload
                   2161:             txt=upload.read()
1.35      dwinter  2162:                                        
                   2163:         if enterList:
                   2164:             txt=enterList
                   2165:             
                   2166:         if upload or enterList:
1.6       dwinter  2167:             txt=txt.replace(",","\n")
                   2168:             txt=txt.replace("\t","\n")
1.12      dwinter  2169:             txt=txt.replace("\r","\n")
1.6       dwinter  2170:             idsTmp=txt.split("\n")
                   2171:             ids=[]
                   2172:             for id in idsTmp: # make sure that no empty lines
                   2173:                 idTmp=id.lstrip().rstrip()
                   2174:                 if len(idTmp)>0:
                   2175:                     
                   2176:                     ids.append(idTmp)
                   2177:                     
                   2178:             #self.REQUEST.SESSION['ids']=" OR ".join(ids)
1.12      dwinter  2179: 
1.6       dwinter  2180:             pt=getattr(self,'filelist.html')
1.7       dwinter  2181:             self.REQUEST.SESSION['searchList']=ids
1.6       dwinter  2182:             return pt(search=ids)
1.7       dwinter  2183:         
1.6       dwinter  2184:         if basketName:
1.7       dwinter  2185:             #TODO: get rid of one of these..
                   2186:             
1.6       dwinter  2187:             pt=getattr(self,'filelist.html')
1.7       dwinter  2188:             return pt(basketName=basketName,numberOfObjects=numberOfObjects)
1.6       dwinter  2189:         
1.102   ! dwinter  2190:         
        !          2191:         result =self.CDLICache.retrieve(hash)
        !          2192:         if result:
        !          2193:            logging.debug("give result from storage2")
        !          2194:            return hash,result
        !          2195:   
1.15      dwinter  2196:         if list is not None: # got already a list
1.83      dwinter  2197:             
                   2198:             logging.debug(" ----List version")
1.6       dwinter  2199:             ret=[]
1.83      dwinter  2200:             fileTree=Set()
                   2201:             
1.6       dwinter  2202:             for fileId in list:
1.83      dwinter  2203:                
                   2204:                 if fileId.find("*")>-1: #check for wildcards
                   2205:                         self.expandFile(fileId,fileTree)
                   2206:                         
1.35      dwinter  2207:                 elif len(fileId.split("."))==1:
1.6       dwinter  2208:                         fileId=fileId+".atf"
1.83      dwinter  2209:                         fileTree.add(fileId)
                   2210:                 #logging.debug("   -----:"+fileId)
                   2211:                 #ret+=self.CDLICatalog({'title':fileId})
                   2212:                 #x =self.getFileObject(fileId)
                   2213:                 #if x is not None:
                   2214:                 #    ret.append(x)
1.35      dwinter  2215:                 
1.83      dwinter  2216:             
                   2217:             
                   2218:             ids = fileTree & self.v_file_ids
1.85      dwinter  2219:             #self.REQUEST.SESSION['fileIds']=ids#store fieldIds in session for further usage
                   2220:             l=makelist(fileTree)[0:]
1.93      dwinter  2221:             #logging.debug("l-list:"+repr(l))
1.85      dwinter  2222:             self.REQUEST.SESSION['fileIds']=l#store fieldIds in session for further usage
                   2223:             self.REQUEST.SESSION['searchList']=l
                   2224:             #self.REQUEST.SESSION['searchList']=['P000001.atf']
                   2225:           
1.83      dwinter  2226:             
1.85      dwinter  2227:             hash = md5.new(repr(makelist(fileTree))).hexdigest() # erzeuge hash als identification
                   2228:             self.REQUEST.SESSION['hash']=hash
                   2229:             #TODO: do I need garbage collection for v_tmpStore ?
1.83      dwinter  2230:             
1.84      dwinter  2231:             #logging.debug("Hash:"+repr(hash))
1.85      dwinter  2232: #        
                   2233: #            if hasattr(self.cdliRoot,'v_tmpStore') and self.cdliRoot.v_tmpStore.has_key(hash): 
                   2234: #               logging.debug("asking for storage")
                   2235: #               res=self.cdliRoot.v_tmpStore[hash]
                   2236: #               if res:
                   2237: #                   if returnHash == True:
                   2238: #                       return hash,res
                   2239: #                   return res
1.83      dwinter  2240:           
1.7       dwinter  2241:             #TODO: get rid of one of these..
1.83      dwinter  2242:             #ids=[x.getObject().getId() for x in ret]
                   2243:             ret=[(self.getFileObject(x),self.getFileObjectLastVersion(x)) for x in ids]
1.84      dwinter  2244:             
                   2245:             #self.REQUEST.SESSION['fileIds']=ids#store fieldIds in session for further usage
                   2246:             #self.REQUEST.SESSION['searchList']=self.REQUEST.SESSION['fileIds']
1.85      dwinter  2247:            
1.25      dwinter  2248:             if display:
                   2249:                 pt=getattr(self,'filelist.html')
                   2250:                 
                   2251:                 return pt(search=ids)
1.83      dwinter  2252:             else:     
                   2253:                 #self.REQUEST.SESSION['hash'] = ret # store in session 
1.102   ! dwinter  2254:                 
1.83      dwinter  2255:                 #logging.debug("HHHHHHNEU:"+repr(self.makelist(ids)))
1.84      dwinter  2256:                 #logging.debug("HHHHHHNEU:"+repr(hash))
1.102   ! dwinter  2257:                 self.CDLICache.store(hash,ret)
        !          2258:                 
1.85      dwinter  2259:                 if returnHash == True:
                   2260:                     return hash,ret
1.25      dwinter  2261:                 return ret
                   2262:         
                   2263:         
1.1       dwinter  2264:         
1.7       dwinter  2265:         if start:
                   2266:             RESPONSE.redirect("filelist.html?start:int="+str(start))
1.85      dwinter  2267: 
1.19      dwinter  2268:     security.declareProtected('Manage','createAllFilesAsSingleFile')
1.1       dwinter  2269:     def createAllFilesAsSingleFile(self,RESPONSE=None):
                   2270:         """download all files"""
                   2271:         
                   2272:         def sortF(x,y):
                   2273:             return cmp(x[0],y[0])
                   2274:         
1.81      casties  2275:         catalog=getattr(self,self.file_catalog)
1.1       dwinter  2276:         #tf,tfilename=mkstemp()
1.66      dwinter  2277:         if not hasattr(self.temp_folder,'downloadCounter'):
                   2278:             self.temp_folder.downloadCounter=0
1.49      dwinter  2279: 
                   2280:         if getattr(self.temp_folder,'downloadCounter',0) > 5:
1.46      dwinter  2281:             return """I am sorry, currently the server has to many requests for downloads, please come back later!"""
1.45      dwinter  2282: 
1.46      dwinter  2283:         self.temp_folder.downloadCounter+=1
                   2284:         self._p_changed=1
1.58      dwinter  2285:         transaction.get().commit()
1.45      dwinter  2286:        
1.1       dwinter  2287:         list=[(x.getId,x) for x in catalog()]
                   2288:         list.sort(sortF)
1.46      dwinter  2289:         
1.45      dwinter  2290: 
1.1       dwinter  2291:         
                   2292:         RESPONSE.setHeader("Content-Disposition","""attachement; filename=%s"""%"all.atf")
                   2293:         RESPONSE.setHeader("Content-Type","application/octet-stream")
1.46      dwinter  2294:         tmp=""
1.1       dwinter  2295:         for l in list:
                   2296:             obj=l[1].getObject()
                   2297:             
                   2298:             if obj.meta_type=="CDLI file":
                   2299:                 
                   2300:                 #os.write(tf,obj.getLastVersion().data)
                   2301:                 if RESPONSE:
1.81      casties  2302:                     RESPONSE.write(obj.getData()[0:])
1.71      dwinter  2303:                     RESPONSE.write("\n")
1.46      dwinter  2304:                 self.temp_folder.downloadCounter-=1 
                   2305:                 self._p_changed=1
1.58      dwinter  2306:         transaction.get().commit()
1.1       dwinter  2307:         #os.close(tf)
                   2308:         #RESPONSE.redirect(self.absolute_url()+"/downloadFile?fn="%tfilename)
                   2309:         return True
                   2310:     
                   2311:     def downloadFile(self,fn):
                   2312:         """download fn - not used yet"""
                   2313:         self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename=%s"""%self.getLastVersion().getId())
                   2314:         self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
                   2315:         self.REQUEST.RESPONSE.write(file(fn).read())
                   2316:         
                   2317:       
                   2318:                 
                   2319:     def hasParent(self):
                   2320:         """returns true falls subfolder"""
                   2321:       
1.81      casties  2322:         if self.aq_parent.meta_type in self.folder_meta_type:
1.1       dwinter  2323:             return True
                   2324:         else:
                   2325:             return False
                   2326:         
                   2327:     def getFolders(self):
                   2328:         """get all subfolders"""
                   2329:         ret=[]
1.81      casties  2330:         folders=self.ZopeFind(self,obj_metatypes=self.folder_meta_type)
1.1       dwinter  2331:         for folder in folders:
                   2332:             ret.append((folder[1],
1.81      casties  2333:                         len(self.ZopeFind(folder[1],obj_metatypes=self.folder_meta_type)),
                   2334:                         len(self.ZopeFind(folder[1],obj_metatypes=self.file_meta_type))
1.1       dwinter  2335:                         ))
                   2336:         return ret
                   2337:     
                   2338:             
1.77      dwinter  2339:     security.declareProtected('manage','index_html')
1.1       dwinter  2340:     def index_html(self):
                   2341:         """main"""
                   2342:         ext=self.ZopeFind(self,obj_ids=["index.html"])
                   2343:         if ext:
                   2344:             return ext[0][1]()
                   2345:         
                   2346:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','CDLIFileFolderMain')).__of__(self)
                   2347:         return pt()
                   2348:     
1.22      dwinter  2349:     
                   2350: manage_addCDLIFileFolderForm=DTMLFile('dtml/folderAdd', globals())
                   2351: 
                   2352:     
                   2353: def manage_addCDLIFileFolder(self, id, title='',
                   2354:                      createPublic=0,
                   2355:                      createUserF=0,
                   2356:                      REQUEST=None):
                   2357:     """Add a new Folder object with id *id*.
                   2358: 
                   2359:     If the 'createPublic' and 'createUserF' parameters are set to any true
                   2360:     value, an 'index_html' and a 'UserFolder' objects are created respectively
                   2361:     in the new folder.
                   2362:     """
                   2363:     ob=CDLIFileFolder()
                   2364:     ob.id=str(id)
                   2365:     ob.title=title
                   2366:     self._setObject(id, ob)
                   2367:     ob=self._getOb(id)
                   2368: 
                   2369:     checkPermission=getSecurityManager().checkPermission
                   2370: 
                   2371:     if createUserF:
                   2372:         if not checkPermission('Add User Folders', ob):
                   2373:             raise Unauthorized, (
                   2374:                   'You are not authorized to add User Folders.'
                   2375:                   )
                   2376:         ob.manage_addUserFolder()
                   2377: 
                   2378:   
                   2379:     if REQUEST is not None:
                   2380:         return self.manage_main(self, REQUEST, update_menu=1)
                   2381:     
                   2382: class CDLIRoot(Folder):
                   2383:     """main folder for cdli"""
                   2384:     
                   2385:     meta_type="CDLIRoot"
1.81      casties  2386:     downloadCounterBaskets=0 # counts the current basket downloads if counter > 10 no downloads are possible
                   2387:     
                   2388:     file_catalog = 'CDLICatalog'
                   2389:     
                   2390:     # word splitter for search
                   2391:     splitter = {'words':cdliSplitter.wordSplitter(),
                   2392:                 'graphemes':cdliSplitter.graphemeSplitter()}
                   2393:     
1.51      dwinter  2394:     
1.102   ! dwinter  2395:     def unicodify(self,txt):
        !          2396:         return unicodify(txt)
        !          2397:     def invalidateOldCacheVersion(self):
        !          2398:         """loescht die alte Version des Cache"""
        !          2399:         del self.v_tmpStore
        !          2400:         return "done"
        !          2401:     
1.86      dwinter  2402:     def viewATF(self,id,RESPONSE):
                   2403:         """view an Object"""
                   2404:         ob = self.CDLICatalog({'title':id})
                   2405:         logging.debug(ob[0].getObject().getLastVersion().absolute_url()+"/view")
                   2406:         if len(ob)>0:
                   2407:             RESPONSE.redirect(ob[0].getObject().getLastVersion().absolute_url()+"/view")
                   2408:         return "not found"
                   2409:     
                   2410:     def history(self,id,RESPONSE):
                   2411:         """view an Object"""
                   2412:         ob = self.CDLICatalog({'title':id})
                   2413:         if len(ob)>0:
                   2414:             RESPONSE.redirect(ob[0].absolute_url+"/history")
                   2415:         return "not found"
                   2416:     
                   2417: 
                   2418:     def downloadLocked(self,id,RESPONSE):
                   2419:         """view an Object"""
                   2420:         ob = self.CDLICatalog({'title':id})
                   2421:         if len(ob)>0:
                   2422:             RESPONSE.redirect(ob[0].absolute_url+"/downloadLocked")
                   2423:         return "not found"
                   2424:     
                   2425:     def download(self,id,RESPONSE):
                   2426:         """view an Object"""
                   2427:         ob = self.CDLICatalog({'title':id})
                   2428:         if len(ob)>0:
                   2429:             RESPONSE.redirect(ob[0].getLastVersion().absolute_url())
                   2430:         return "not found"
                   2431:     def addCDLIFileObjectForm(self,id,RESPONSE):
                   2432:         """view an Object"""
                   2433:         ob = self.CDLICatalog({'title':id})
                   2434:         if len(ob)>0:
                   2435:             RESPONSE.redirect(ob[0].absolute_url+"/addCDLIFileObjectForm")
                   2436:         return "not found"
                   2437:     
                   2438:     def addVersionedFileObjectForm(self,id,RESPONSE):
                   2439:         """view an Object"""
                   2440:         ob = self.CDLICatalog({'title':id})
                   2441:         if len(ob)>0:
                   2442:             RESPONSE.redirect(ob[0].absolute_url+"/addVersionedFileObjectForm")
                   2443:         return "not found"
                   2444:     
                   2445:     def unlock(self,id,RESPONSE):
                   2446:         """view an Object"""
                   2447:         ob = self.CDLICatalog({'title':id})
                   2448:         if len(ob)>0:
                   2449:             RESPONSE.redirect(ob[0].absolute_url+"/unlock")
                   2450:         return "not found"
                   2451:     
1.83      dwinter  2452:     def getFileObject(self,fileId):
1.85      dwinter  2453:         """get an object"""
1.83      dwinter  2454:         x=self.v_files.get(fileId)
                   2455:         #logging.debug(x)
                   2456:         return x
                   2457:     
                   2458:     def getFileObjectLastVersion(self,fileId):
1.85      dwinter  2459:         """get an object"""
1.83      dwinter  2460:         x=self.v_files_lastVersion.get(fileId)
1.95      dwinter  2461:         #logging.debug("lastVersion: "+repr(x))
1.83      dwinter  2462:         return x
                   2463:     
1.85      dwinter  2464:     def showFileIds(self):
                   2465:         """showIds"""
                   2466:         return self.v_file_ids
                   2467:     
1.83      dwinter  2468:     def generateFileBTree(self):
                   2469:         """erzeuge einen Btree aus allen Files"""
                   2470:         self.v_files = OOBTree()
                   2471:         self.v_files_lastVersion = OOBTree()
                   2472:         self.v_file_ids = Set()
                   2473:         
                   2474:         for x in self.CDLICatalog.searchResults():
                   2475:             
                   2476:             self.v_files.update({x.getId:x.getObject()})
                   2477:             self.v_files_lastVersion.update({x.getId:x.getObject().getLastVersion()})
                   2478:             self.v_file_ids.add(x.getId)
                   2479:             logging.debug("add:"+x.getId+"XXX"+repr(x.getObject()))
                   2480:         
1.85      dwinter  2481:         return True
                   2482:     
                   2483:     
                   2484:     def updateOrAddToFileBTree(self,obj):
                   2485:         """update a BTree"""
                   2486:         self.v_files.update({obj.getId():obj})
                   2487:         self.v_files_lastVersion.update({obj.getId():obj.getLastVersion()})
                   2488:         
                   2489:         self.v_file_ids.add(obj.getId())
                   2490:         logging.debug("update:"+obj.getId()+"XXX"+repr(obj))
                   2491:         
                   2492:     def deleteFromBTree(self,objId):
                   2493:         """delete an obj"""
                   2494:         self.v_files.pop(objId)
                   2495:         self.v_files_lastVersion.pop(objId)
                   2496:         self.v_file_ids.remove(objId)
                   2497:         
                   2498: 
                   2499:  
1.73      dwinter  2500:     def deleteFiles(self,ids):
1.81      casties  2501:         """delete files"""
1.73      dwinter  2502:         for id in ids:
                   2503:             founds=self.CDLICatalog.search({'title':id.split(".")[0]})
                   2504:             if founds:
1.81      casties  2505:                 logging.debug("deleting %s"%founds)
1.73      dwinter  2506:                 folder=founds[0].getObject().aq_parent #get the parent folder of the object
1.81      casties  2507:                 logging.debug("deleting from %s"%folder)
                   2508:                 cut=folder.delete([founds[0].getId]) #cut it out
                   2509: 
1.73      dwinter  2510: 
                   2511: 
1.81      casties  2512:     def searchText(self, query, index='graphemes'):
                   2513:         """searches query in the fulltext index and returns a list of file ids/P-numbers"""
                   2514:         # see also: http://www.plope.com/Books/2_7Edition/SearchingZCatalog.stx#2-13
                   2515:         logging.debug("searchtext for '%s' in index %s"%(query,index))
                   2516:         #import Products.ZCTextIndex.QueryParser
                   2517:         #qp = QueryParser.QueryParser()
                   2518:         #logging.debug()
                   2519:         idxQuery = {index:{'query':query}}
                   2520:         idx = getattr(self, self.file_catalog)
                   2521:         # do search
                   2522:         resultset = idx.search(query_request=idxQuery,sort_index='textid')
                   2523:         # put only the P-Number in the result 
                   2524:         results = [res.getId[:7] for res in resultset]
                   2525:         logging.debug("searchtext: found %d texts"%len(results))
                   2526:         return results
                   2527: 
                   2528: 
                   2529:     def getFile(self, pnum):
                   2530:         """get the translit file with the given pnum"""
                   2531:         f = getattr(self, self.file_catalog).search({'textid':pnum})
                   2532:         if not f:
                   2533:             return ""
1.71      dwinter  2534:         
1.81      casties  2535:         return f[0].getObject().getData()
                   2536:          
1.57      dwinter  2537: 
1.74      dwinter  2538:     def showFile(self,fileId,wholePage=False):
1.71      dwinter  2539:         """show a file
                   2540:         @param fileId: P-Number of the document to be displayed
                   2541:         """
1.81      casties  2542:         f=getattr(self, self.file_catalog).search({'textid':fileId})
1.51      dwinter  2543:         if not f:
                   2544:             return ""
                   2545:         
1.74      dwinter  2546:         if wholePage:
1.81      casties  2547:             logging.debug("show whole page")
                   2548:             return f[0].getObject().getContentObject().view()
1.74      dwinter  2549:         else:
                   2550:             return f[0].getObject().getLastVersionFormattedData()
1.55      dwinter  2551:     
1.56      dwinter  2552: 
1.81      casties  2553:     def showWordInFile(self,fileId,word,indexName='graphemes',regExp=False,):
                   2554:         """get lines with word from FileId"""
                   2555:         logging.debug("showwordinfile word='%s' index=%s file=%s"%(word,indexName,fileId)) 
1.56      dwinter  2556:         
1.81      casties  2557:         file = formatAtfFullLineNum(self.getFile(fileId))
1.66      dwinter  2558:         ret=[]
1.71      dwinter  2559:         
1.81      casties  2560:         # add whitespace before and whitespace and line-end to splitter bounds expressions
                   2561:         bounds = self.splitter[indexName].bounds
                   2562:         splitexp = "(%s|\s)(%%s)(%s|\s|\Z)"%(bounds,bounds)
                   2563:         # clean word expression 
                   2564:         # TODO: this should use QueryParser itself
                   2565:         # take out double quotes
                   2566:         word = word.replace('"','')
                   2567:         # take out ignorable signs
                   2568:         ignorable = self.splitter[indexName].ignorex
                   2569:         word = ignorable.sub('', word)
                   2570:         # compile into regexp objects and escape parens
                   2571:         wordlist = [re.compile(splitexp%re.escape(w)) for w in word.split(' ')]
                   2572:             
                   2573:         for line in file.splitlines():
1.71      dwinter  2574:             for word in wordlist:
1.81      casties  2575:                 #logging.debug("showwordinfile: searching for %s in %s"%(word.pattern,ignoreable.sub('',line)))
                   2576:                 if word.search(ignorable.sub('',line)):
                   2577:                     line = formatAtfLineHtml(line)
                   2578:                     ret.append(line)
                   2579:                     break
                   2580:                     
1.66      dwinter  2581:         return ret
1.56      dwinter  2582: 
1.81      casties  2583:     
                   2584:     def showWordInFiles(self,fileIds,word,indexName='graphemes',regExp=False):
                   2585:         """
                   2586:         get lines with word from all ids in list FileIds.
                   2587:         returns dict with id:lines pairs.
                   2588:         """
                   2589:         logging.debug("showwordinfiles word='%s' index=%s file=%s"%(word,indexName,fileIds))
1.51      dwinter  2590:         
1.81      casties  2591:         return dict([(id,self.showWordInFile(id, word, indexName, regExp)) for id in fileIds])
                   2592:     
                   2593: 
                   2594:     def tagWordInFile(self,fileId,word,indexName='graphemes',regExp=False):
                   2595:         """get text with word highlighted from FileId"""
                   2596:         logging.debug("tagwordinfile word='%s' index=%s file=%s"%(word,indexName,fileId)) 
                   2597:         
                   2598:         file=self.getFile(fileId)
                   2599:         tagStart=u'<span class="found">'
                   2600:         tagEnd=u'</span>'
                   2601:         tagStr=tagStart + u'%%s' + tagEnd
1.66      dwinter  2602:         ret=[]
1.71      dwinter  2603:         
1.81      casties  2604:         # add whitespace to splitter bounds expressions and compile into regexp object
                   2605:         bounds = self.splitter[indexName].bounds
                   2606:         wordsplit = re.compile("(%s|\s)"%bounds)
                   2607:         # clean word expression 
                   2608:         # TODO: this should use QueryParser itself
                   2609:         word = word.replace('"','') # take out double quotes
                   2610:         # take out ignoreable signs
                   2611:         ignorable = self.splitter[indexName].ignorex
                   2612:         word = ignorable.sub('', word)
                   2613:         # split search terms by blanks
                   2614:         words = word.split(' ')
                   2615:         # split search terms again (for grapheme search with words)
                   2616:         splitwords = dict(((w,self.splitter[indexName].process([w])) for w in words))
1.71      dwinter  2617:             
1.81      casties  2618:         for line in file.splitlines():
1.79      casties  2619:             line = unicodify(line)
1.81      casties  2620:             # ignore lemma and other lines
                   2621:             if line.lstrip().startswith('#lem:'):
                   2622:                 continue
                   2623:             # ignore p-num line
                   2624:             if line.startswith('&P'):
                   2625:                 continue
                   2626:             # ignore version lines
                   2627:             if line.startswith('#version'):
                   2628:                 continue
                   2629:             # ignore atf type lines
                   2630:             if line.startswith('#atf:'):
                   2631:                 continue
                   2632: 
                   2633:             # first scan
                   2634:             hitwords = []
                   2635:             for w in words:
                   2636:                 if ignorable.sub('',line).find(w) > -1:
                   2637:                     # word is in line
                   2638:                     # append split word for grapheme search with words
                   2639:                     hitwords.extend(splitwords[w])
                   2640:                     #hitwords.extend(wordsplit.split(w))
                   2641:                    
                   2642:             # examine hits closer
                   2643:             if hitwords:
                   2644:                 # split line into words
                   2645:                 parts = wordsplit.split(line)
                   2646:                 line = ""
                   2647:                 for p in parts:
                   2648:                     #logging.debug("tagwordinfile: searching for %s in %s"%(p,hitwords))
                   2649:                     # reassemble line
                   2650:                     if ignorable.sub('', p) in hitwords:
                   2651:                         #logging.debug("tagwordinfile: found %s in %s"%(p,hitwords))
                   2652:                         # this part was found
                   2653:                         line += tagStart + formatAtfHtml(p) + tagEnd
                   2654:                     else:
                   2655:                         line += formatAtfHtml(p)
                   2656:                 
                   2657:             else:
                   2658:                 # no hits
                   2659:                 line = formatAtfHtml(line)
                   2660:             
                   2661:             ret.append(line)
                   2662:                         
                   2663:         return u'<br>\n'.join(ret)
                   2664: 
1.66      dwinter  2665: 
                   2666: 
1.81      casties  2667:     def tagWordInFiles(self,fileIds,word,indexName='graphemes',regExp=False):
                   2668:         """
                   2669:         get texts with highlighted word from all ids in list FileIds.
                   2670:         returns dict with id:text pairs.
                   2671:         """
                   2672:         logging.debug("tagwordinfiles word='%s' index=%s file=%s"%(word,indexName,fileIds)) 
                   2673:         return dict([(id,self.tagWordInFile(id, word, indexName, regExp)) for id in fileIds])
                   2674:     
1.56      dwinter  2675: 
1.82      casties  2676:     def getFileVersionList(self, pnum):
                   2677:         """get the version history as a list for the translit file with the given pnum"""
                   2678:         f = getattr(self, self.file_catalog).search({'textid':pnum})
                   2679:         if not f:
                   2680:             return []
                   2681:         
                   2682:         return f[0].getObject().getVersionList()
                   2683:          
                   2684: 
1.37      dwinter  2685:     def URLquote(self,str):
                   2686:         """quote url"""
                   2687:         return urllib.quote(str)
                   2688:     
                   2689:     def URLunquote(self,str):
                   2690:         """unquote url"""
                   2691:         return urllib.unquote(str)
                   2692:     
1.58      dwinter  2693:     def URLquote_plus(self,str):
                   2694:         """quote url"""
                   2695:         return urllib.quote_plus(str)
                   2696:     
                   2697:     def URLunquote_plus(self,str):
                   2698:         """unquote url"""
                   2699:         return urllib.unquote_plus(str)
                   2700:     
1.37      dwinter  2701:     
1.26      dwinter  2702:     def forceunlock(self):
                   2703:         "break all locks"
                   2704:         ret=[]
                   2705:         for f in self.ZopeFind(self,obj_metatypes="CDLI file",search_sub=1):
                   2706:            un=f[1].forceunlock()
1.39      dwinter  2707: 
1.26      dwinter  2708:            if un and un !="":
                   2709:                ret.append((f[0],un))
1.46      dwinter  2710: 
1.61      dwinter  2711:         return ret
1.71      dwinter  2712:                                         
1.61      dwinter  2713: 
1.26      dwinter  2714:     def getChangesByAuthor(self,author,n=100):
1.25      dwinter  2715:         """getChangesByAuthor"""
1.26      dwinter  2716:         zcat=self.CDLIObjectsCatalog
                   2717:         res=zcat({'lastEditor':author,
1.25      dwinter  2718:                      'sort_on':'getTime',
                   2719:                      'sort_order':'descending',
                   2720:                      'sort_limit':n})[:n ]
1.26      dwinter  2721:                        
                   2722:         return res
                   2723:     
                   2724:     def getChangesByAuthor_html(self,author,n=100):
                   2725:         """html output for changes by author"""
                   2726:         tmp={}
                   2727:         list=[]                         
                   2728:         for x in self.getChangesByAuthor(author):
                   2729:            nr=x.getObject().getVersionNumber()
                   2730:            id=x.getObject().aq_parent.getId()
                   2731:            #hinzufuegen, wenn Version neuer als die 
                   2732:            if tmp.get(id,(0,0))[1] < nr:
                   2733:                 tmp[id]=(x.getObject().aq_parent,nr)
                   2734: 
                   2735:      
1.45      dwinter  2736:         return self.cdli_main.findObjectsFromListWithVersion(list=tmp.values(),author=author)           
1.26      dwinter  2737:         
1.25      dwinter  2738:     def getLastChanges(self,n=100):
                   2739:         """get the last n changes""" 
                   2740:         n=int(n)                   
                   2741:         zcat=self.CDLICatalog
                   2742:         return zcat({'sort_on':'getLastChangeDate',
                   2743:                      'sort_order':'descending',
                   2744:                      'sort_limit':n})[:n ]
                   2745:      
                   2746:     
                   2747:     def getLastChanges_html(self,n=100):
                   2748:         """get the last n changes"""
                   2749:         list = [x.getId for x in self.getLastChanges(n)]
                   2750:         return self.cdli_main.findObjectsFromList(list=list,display=True)
                   2751:                                        
1.24      dwinter  2752:     def refreshTxt(self,txt="",threadName=None):
1.22      dwinter  2753:         """txt fuer refresh"""
                   2754:   
1.24      dwinter  2755:         return """ 2;url=%s?repeat=%s """%(self.absolute_url()+txt,threadName)
1.22      dwinter  2756: 
1.87      dwinter  2757:     def refreshTxtBasket(self,txt="",threadName=None):
                   2758:         """txt fuer refresh"""
                   2759:   
                   2760:         return """ 2;url=%s?repeat=%s """%(txt,threadName)
                   2761: 
1.22      dwinter  2762:     
1.24      dwinter  2763:     def getResult(self,threadName=None):
1.22      dwinter  2764:        """result of thread"""
                   2765:        try:
1.24      dwinter  2766:         return self._v_uploadATF[threadName].getResult()
1.22      dwinter  2767:        except:
                   2768:         return "One moment, please"
                   2769:     
1.24      dwinter  2770:         
                   2771:     def checkThreads(self):
                   2772:         """check threads"""
1.42      dwinter  2773:         ret="<html><body>"
                   2774:         for thread in threading.enumerate():
1.45      dwinter  2775:            ret+="<p>%s (%s): %s</p>"%(repr(thread),thread.getName(),thread.isAlive())
1.42      dwinter  2776:        
                   2777:         return ret
                   2778:                                        
                   2779:                                            
1.73      dwinter  2780:     def uploadATFRPC(self,data,username):
                   2781:         """upload an atffile via xml-rpc"""
                   2782:         uploader=uploadATFThread()
                   2783:         
                   2784:         #generate an random id for the upload object
                   2785:         from random import randint
                   2786:         if (not self.REQUEST.SESSION.get('idTmp',None)):
                   2787: 
                   2788:             idTmp=str(randint(0,1000000000))
                   2789:             self.REQUEST.SESSION['idTmp']=idTmp
                   2790:         else:
                   2791:             idTmp=self.REQUEST.SESSION.get('idTmp',None)
                   2792:             
                   2793:         
                   2794:         uploader.set(data,0,username,idTmp)
                   2795:         
                   2796:         stObj=uploader.run()
                   2797:         
                   2798:         processor=uploadATFfinallyThread()
                   2799:         
                   2800:         basketname=stObj.returnValue['basketNameFromFile']
                   2801:         
                   2802:         processor.set("uploadchanged",basketname=basketname,SESSION=stObj.returnValue,username=username,serverport=self.REQUEST['SERVER_PORT'])
                   2803:         
                   2804:         processor.run()
                   2805:         
                   2806:         
                   2807:         return generateXMLReturn(stObj.returnValue)
                   2808:         
1.22      dwinter  2809:     def uploadATF(self,repeat=None,upload=None,basketId=0,RESPONSE=None):
1.69      dwinter  2810:         """upload an atf file / basket file"""
1.22      dwinter  2811:         #self._v_uploadATF.returnValue=None
1.71      dwinter  2812:         
                   2813:         #generate an random id for the upload thread
1.60      dwinter  2814:         from random import randint
1.61      dwinter  2815:         if (not self.REQUEST.SESSION.get('idTmp',None)):
1.22      dwinter  2816: 
1.60      dwinter  2817:             idTmp=str(randint(0,1000000000))
                   2818:             self.REQUEST.SESSION['idTmp']=idTmp
                   2819:         else:
                   2820:             idTmp=self.REQUEST.SESSION.get('idTmp',None)
                   2821:             
1.71      dwinter  2822:     
1.22      dwinter  2823:         threadName=repeat
                   2824:         if not threadName or threadName=="":
1.71      dwinter  2825:             #new thread not called from the waiting page
1.22      dwinter  2826:             tmpVar=False
1.24      dwinter  2827:        
1.22      dwinter  2828:             thread=uploadATFThread()
1.24      dwinter  2829:             threadName=thread.getName()[0:]                                
1.36      dwinter  2830:             if (not hasattr(self,'_v_uploadATF')):
1.24      dwinter  2831:                    self._v_uploadATF={}
                   2832:                                        
                   2833:             self._v_uploadATF[threadName]=thread
1.22      dwinter  2834:             #self._xmltrans.start()
                   2835:             #thread=Thread(target=self._v_uploadATF)
1.60      dwinter  2836:             logging.info("set thread. extern")
                   2837:             self._v_uploadATF[threadName].set(upload,basketId,self.REQUEST['AUTHENTICATED_USER'],idTmp,serverport=self.REQUEST['SERVER_PORT'])
1.22      dwinter  2838:             #thread.start()
1.60      dwinter  2839:             logging.info("start thread. extern")
1.24      dwinter  2840:             self._v_uploadATF[threadName].start()
1.22      dwinter  2841: 
                   2842:             
1.24      dwinter  2843:             self.threadName=self._v_uploadATF[threadName].getName()[0:]
1.22      dwinter  2844:             wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
                   2845: 
                   2846:             if wait_template:
                   2847:                 return wait_template[0][1]()
                   2848:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadATFWait.zpt')).__of__(self)
1.24      dwinter  2849:             return pt(txt='/uploadATF',threadName=threadName)
1.22      dwinter  2850:             #_v_xmltrans.run()
                   2851:             
                   2852:         else:
                   2853:             #recover thread, if lost
1.36      dwinter  2854:             if (not hasattr(self,'_v_uploadATF')):
1.24      dwinter  2855:                self._v_uploadATF={}
                   2856:             if not self._v_uploadATF.get(threadName,None):
1.22      dwinter  2857:                  for thread in threading.enumerate():
                   2858:                          if threadName == thread.getName():
1.24      dwinter  2859:                                        self._v_uploadATF[threadName]=thread
                   2860:                                        
1.60      dwinter  2861:             if self._v_uploadATF.get(threadName,None) and (not self._v_uploadATF[threadName].returnValue):
1.22      dwinter  2862:         
                   2863: 
                   2864:                 wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
                   2865:                 if wait_template:
                   2866:                         return wait_template[0][1]()
                   2867:                 
                   2868:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadATFWait.zpt')).__of__(self)
                   2869: 
1.24      dwinter  2870:                 return pt(txt='/uploadATF',threadName=threadName)
1.22      dwinter  2871:                 
                   2872:             else:
1.60      dwinter  2873:                 tmp=getattr(self.temp_folder,idTmp).returnValue
1.71      dwinter  2874:  
1.22      dwinter  2875:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadCheck.zpt')).__of__(self)
1.39      dwinter  2876: 
1.47      dwinter  2877:                 return pt(changed=tmp['changed'],lockerrors=tmp['lockerrors'],errors=tmp['errors'],dir=tmp['dir'],newPs=tmp['newPs'],basketLen=tmp['basketLen'],numberOfFiles=tmp['numberOfFiles'],
1.22      dwinter  2878:                   basketNameFromId=tmp['basketNameFromId'],basketNameFromFile=tmp['basketNameFromFile'],basketId=tmp['basketId'])
1.30      dwinter  2879:                      
                   2880:     def redoUpload(self,threadName):
                   2881:        """redo the upload"""
                   2882:        tmp=self.cdli_main.tmpStore2[threadName]
                   2883:        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadCheck.zpt')).__of__(self)
1.45      dwinter  2884:        return pt(changed=tmp['changed'],lockerrors=tmp['lockerrors'],errors=tmp['errors'],dir=tmp['dir'],newPs=tmp['newPs'],basketLen=tmp['basketLen'],numberOfFiles=tmp['numberOfFiles'],
1.30      dwinter  2885:                   basketNameFromId=tmp['basketNameFromId'],basketNameFromFile=tmp['basketNameFromFile'],basketId=tmp['basketId'])
                   2886:                  
1.22      dwinter  2887:     def uploadATFfinally(self,procedure='',comment="",basketname='',unlock=None,repeat=None,RESPONSE=None):
                   2888:         """nowupload the files"""
                   2889:        
                   2890:        
                   2891:        
                   2892:         threadName=repeat
                   2893:         if not threadName or threadName=="":
1.24      dwinter  2894:             thread=uploadATFfinallyThread()
                   2895:             threadName=thread.getName()[0:]
1.36      dwinter  2896: 
1.35      dwinter  2897:             if (not hasattr(self,'_v_uploadATF')):
1.46      dwinter  2898:                                 self._v_uploadATF={}
1.36      dwinter  2899: 
1.43      dwinter  2900: 
1.24      dwinter  2901:             self._v_uploadATF[threadName]=thread
1.22      dwinter  2902: 
1.60      dwinter  2903:             idTmp=self.REQUEST.SESSION['idTmp']
                   2904:             stObj=getattr(self.temp_folder,idTmp)
                   2905:             self._v_uploadATF[threadName].set(procedure,comment=comment,basketname=basketname,unlock=unlock,SESSION=stObj.returnValue,username=self.REQUEST['AUTHENTICATED_USER'],serverport=self.REQUEST['SERVER_PORT'])
1.22      dwinter  2906: 
1.24      dwinter  2907:             self._v_uploadATF[threadName].start()
1.22      dwinter  2908: 
                   2909:             
1.24      dwinter  2910:             
1.22      dwinter  2911:             wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
                   2912: 
                   2913:             if wait_template:
                   2914:                 return wait_template[0][1]()
                   2915:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadATFWait.zpt')).__of__(self)
                   2916: 
1.24      dwinter  2917:             return pt(txt='/uploadATFfinally',threadName=threadName)
1.22      dwinter  2918:             #_v_xmltrans.run()
                   2919:         
                   2920:         else:
                   2921:             #recover thread, if lost
                   2922:             if not hasattr(self,'_v_uploadATF'):
1.24      dwinter  2923:                self._v_uploadATF={}
                   2924:             if not self._v_uploadATF.get(threadName,None):
1.22      dwinter  2925:                  for thread in threading.enumerate():
                   2926:                          if threadName == thread.getName():
1.24      dwinter  2927:                                        self._v_uploadATF[threadName]=thread
1.22      dwinter  2928:                                        
1.24      dwinter  2929:             if self._v_uploadATF.get(threadName,None) and (self._v_uploadATF[threadName] is not None) and (not self._v_uploadATF[threadName].end) :
1.22      dwinter  2930: 
                   2931:                 wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
                   2932:                 if wait_template:
                   2933:                         return wait_template[0][1]()
                   2934:                 
                   2935:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadATFWait.zpt')).__of__(self)
1.24      dwinter  2936:                 return pt(txt='/uploadATFfinally',threadName=threadName)
1.22      dwinter  2937:             else:
1.85      dwinter  2938:               
                   2939:              
                   2940:               idTmp=self.REQUEST.SESSION['idTmp']
                   2941:               stObj=getattr(self.temp_folder,idTmp) 
1.60      dwinter  2942:               self.REQUEST.SESSION['idTmp']=None
1.85      dwinter  2943:              
                   2944:               #update changed
                   2945:               logging.debug("dir:"+repr(stObj.returnValue['changed']))
                   2946:               for x in stObj.returnValue['changed']:
                   2947:                     ob=self.CDLICatalog.search({'title':x[0]})
                   2948:                    
                   2949:                     self.cdliRoot.updateOrAddToFileBTree(ob[0].getObject())
1.22      dwinter  2950:               if RESPONSE is not None:
                   2951:                   RESPONSE.redirect(self.absolute_url())
                   2952: 
1.49      dwinter  2953:     def importFiles(self,comment="",author="" ,folderName="/Users/dwinter/atf", files=None,ext=None):
1.1       dwinter  2954:         """import files"""
1.81      casties  2955:         logging.debug("importFiles folderName=%s files=%s ext=%s"%(folderName,files,ext))
1.22      dwinter  2956:         root=self.cdli_main
1.49      dwinter  2957:         count=0
1.3       dwinter  2958:         if not files:
                   2959:             files=os.listdir(folderName)
                   2960:             
1.1       dwinter  2961:         for f in files:
                   2962:             folder=f[0:3]
                   2963:             f2=f[0:5]
1.85      dwinter  2964:             
                   2965:             #check if main folder PXX already exists
1.22      dwinter  2966:             obj=self.ZopeFind(root,obj_ids=[folder])
1.81      casties  2967:             logging.debug("importFiles: folder=%s f2=%s obj=%s"%(folder,f2,obj)) 
1.19      dwinter  2968:             if ext:
1.65      dwinter  2969:                 ext.result="<p>adding: %s </p>"%f+ext.result
1.81      casties  2970: 
1.85      dwinter  2971:             
                   2972:             if not obj: # if not create it
1.22      dwinter  2973:                 manage_addCDLIFileFolder(root,folder,folder)
                   2974:                 fobj=getattr(root,folder)
1.58      dwinter  2975:                 #transaction.get().commit()                           
1.81      casties  2976: 
1.1       dwinter  2977:             else:
                   2978:                 fobj=obj[0][1]
                   2979:             
1.85      dwinter  2980:             #check IF PYYYYY already exist
1.1       dwinter  2981:             obj2=fobj.ZopeFind(fobj,obj_ids=[f2])
1.81      casties  2982:             logging.debug("importFiles: fobj=%s obj2=%s"%(fobj,obj2)) 
1.1       dwinter  2983:         
1.85      dwinter  2984:             if not obj2:# if not create it
1.1       dwinter  2985:                 manage_addCDLIFileFolder(fobj,f2,f2)
                   2986:                 fobj2=getattr(fobj,f2)
                   2987:         
                   2988:             else:
                   2989:                 fobj2=obj2[0][1]
                   2990:               
1.85      dwinter  2991:             # not add the file
1.48      dwinter  2992:             file2=os.path.join(folderName,f)  
1.1       dwinter  2993:             id=f
1.81      casties  2994:             logging.debug("importFiles: addCDLIFile fobj2=%s, f=%s file2=%s"%(fobj2,repr(f),repr(file2)))
                   2995:             fobj2.addFile(vC='',file=file(file2),author=author,newName=f)
1.66      dwinter  2996:             count+=1
1.85      dwinter  2997:             
                   2998:             #now add the file to the storage
                   2999:             ob = getattr(fobj2,f)
                   3000:             self.cdliRoot.updateOrAddToFileBTree(ob)
                   3001:             
1.81      casties  3002:             if count%100==0:
                   3003:                 logging.debug("importfiles: committing")
1.66      dwinter  3004:                 transaction.get().commit()
1.81      casties  3005: 
                   3006:         transaction.get().commit()
1.3       dwinter  3007:         return "ok"
1.22      dwinter  3008:          
                   3009: 
                   3010: manage_addCDLIRootForm=DTMLFile('dtml/rootAdd', globals())
1.1       dwinter  3011: 
                   3012:     
1.22      dwinter  3013: def manage_addCDLIRoot(self, id, title='',
1.1       dwinter  3014:                      createPublic=0,
                   3015:                      createUserF=0,
                   3016:                      REQUEST=None):
                   3017:     """Add a new Folder object with id *id*.
                   3018: 
                   3019:     If the 'createPublic' and 'createUserF' parameters are set to any true
                   3020:     value, an 'index_html' and a 'UserFolder' objects are created respectively
                   3021:     in the new folder.
                   3022:     """
1.22      dwinter  3023:     ob=CDLIRoot()
1.1       dwinter  3024:     ob.id=str(id)
                   3025:     ob.title=title
1.61      dwinter  3026:     try:
1.66      dwinter  3027:         self._setObject(id, ob)
1.61      dwinter  3028:     except:
1.66      dwinter  3029:         pass
1.1       dwinter  3030:     ob=self._getOb(id)
                   3031: 
                   3032:     checkPermission=getSecurityManager().checkPermission
                   3033: 
                   3034:     if createUserF:
                   3035:         if not checkPermission('Add User Folders', ob):
                   3036:             raise Unauthorized, (
                   3037:                   'You are not authorized to add User Folders.'
                   3038:                   )
                   3039:         ob.manage_addUserFolder()
                   3040: 
                   3041:   
                   3042:     if REQUEST is not None:
1.22      dwinter  3043:         return self.manage_main(self, REQUEST, update_menu=1)    
                   3044:  

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