1: """CDLI extensions of the filearchive"""
2: from Products.versionedFile.extVersionedFile import *
3: from Products.ZCatalog.CatalogPathAwareness import CatalogAware
4: import os.path
5: import os
6: import urlparse
7: import urllib
8: import cgi
9: from OFS.OrderedFolder import OrderedFolder
10: from OFS.SimpleItem import SimpleItem
11: import time
12: from OFS.Folder import manage_addFolder
13: import re
14: from AccessControl import ClassSecurityInfo
15: from Acquisition import Implicit
16: from Globals import Persistent
17: from threading import Thread
18: from ZPublisher.HTTPRequest import HTTPRequest
19: from ZPublisher.HTTPResponse import HTTPResponse
20: from ZPublisher.BaseRequest import RequestContainer
21: import threading
22: from BTrees.OOBTree import OOBTree, OOTreeSet
23: import logging
24: import transaction
25: import copy
26: import codecs
27: import sys
28: from BTrees.IOBTree import IOBTree
29: import cdliSplitter
30: from sets import Set
31: import md5
32: from DownloadBasket import DownloadBasketFinallyThread
33: from types import *
34:
35: def makelist(mySet):
36: x = list(mySet)
37: x.sort()
38: return x
39:
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:
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('<','<')
71: l = l.replace('>','>')
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:
86:
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:
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:
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:
223: class BasketContent(SimpleItem):
224: """classe fuer den Inhalt eines Baskets"""
225:
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:
234: def __init__(self,content=[]):
235: """content"""
236:
237: self.setContent(content[0:])
238:
239: def getContent(self,filtered=True):
240: return self.contentList
241:
242: def getContentOld(self,filtered=True):
243: """get content"""
244: logging.debug("content object: content List %s"%self.contentList)
245: ret=[]
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
259:
260: def allContent(self):
261: """get all content"""
262: return self.getContent(filtered=False)
263:
264: def setContent(self,content):
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:
273: def numberOfItems(self):
274: """number"""
275:
276: return len(self.getContent())
277:
278:
279: class uploadATFfinallyThread(Thread):
280: """class for adding uploaded filed (temporarily stored in the staging area at /tmp"""
281:
282: def __init__(self):
283: """init for uploadATFfinallyThread"""
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"):
290: """set start values for the thread"""
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
298:
299:
300: def __call__(self):
301: """call of the thread (equals run)"""
302: self.run()
303: return True
304:
305: def getContext(self, app,serverport="8080"):
306: """get the context within the ZODB"""
307:
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:
317:
318: def run(self):
319: """run"""
320:
321: self.result=""
322: #find context within ZODB
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:
329: #add the files
330: self.uploadATFfinallyThread(ctx,self.procedure,comment=self.comment,basketname=self.basketname,unlock=self.unlock,SESSION=self.SESSION,username=self.username)
331: #commit the transactions
332: transaction.get().commit()
333: conn.close()
334: #set flag for end of this method
335: self.end=True
336: logging.info("ended")
337: return True
338:
339: def __del__(self):
340: """delete"""
341:
342:
343:
344: def getResult(self):
345: """method for accessing result"""
346:
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"""
351: #TODO: make this configurable, at the moment, rootFolder for cdli has to be cdliRoot
352: ctx2=ctx.cdliRoot
353:
354: self.result+="<h2>Start processing</h2>"
355:
356: #shall I only upload the changed files?
357: logging.debug("uploadATFfinally procedure: %s"%procedure)
358: if procedure=="uploadchanged":
359: changed=[x[0] for x in SESSION.get('changed',[])]
360: uploadFns=changed+SESSION.get('newPs',[])
361:
362: #or all
363: elif procedure=="uploadAll":
364: uploadFns=[]
365: for x in os.listdir(SESSION['tmpdir']):
366: if not x in SESSION['lockerrors']:
367: uploadFns.append(x)
368:
369: #or maybe nothing
370: elif procedure=="noupload":
371: return True
372: else:
373: uploadFns=[]
374:
375: #do first the changed files
376: i=0
377: for fn in uploadFns:
378: logging.debug("uploadATFfinally uploadFn=%s"%fn)
379: i+=1
380: founds=ctx2.CDLICatalog.search({'title':fn})
381: if len(founds)>0:
382: SESSION['author']=str(username)
383: self.result="<p>Changing : %s"%fn+self.result
384: logging.debug("uploadatffinallythread changing:%s"%fn+self.result)
385: founds[0].getObject().manage_addCDLIFileObject('',comment,SESSION['author'],file=os.path.join(SESSION['tmpdir'],fn),from_tmp=True)
386: if i%200==0:
387: transaction.get().commit()
388: logging.debug("uploadatffinallythread changing: do commit")
389:
390: transaction.get().commit()
391: logging.debug("uploadatffinallythread changing: last commit")
392:
393: #now add the new files
394: newPs=SESSION['newPs']
395: if len(newPs)>0:
396: tmpDir=SESSION['tmpdir']
397: logging.debug("uploadatffinallythread adding start")
398: self.result="<p>Adding files</p>"+self.result
399: #TODO: make this configurable, at the moment base folder for the files has to be cdli_main
400: ctx2.importFiles(comment=comment,author=str(username) ,folderName=tmpDir, files=newPs,ext=self)
401: logging.debug("uploadatffinallythread adding finished")
402:
403: #unlock locked files?
404: if unlock:
405: logging.debug("uploadatffinallythread unlocking start")
406: self.result="<p>Unlock files</p>"+self.result
407: unlockFns=[]
408: for x in os.listdir(SESSION['tmpdir']):
409: if not x in SESSION['errors']:
410: unlockFns.append(x)
411:
412: logging.debug("unlocking have now what to unlock")
413:
414: for fn in unlockFns:
415: #logging.info("will unlock: %s"%fn)
416: founds=ctx2.CDLICatalog.search({'title':fn})
417: #logging.info("found it: %s"%repr(founds))
418: if len(founds)>0:
419: #logging.info("unlock: %s"%founds[0].getObject().getId())
420: SESSION['author']=str(username)
421: founds[0].getObject().lockedBy=""
422:
423: logging.debug("uploadatffinallythread unlocking done")
424:
425: #if a basketname is given, add files to the basket
426: if not (basketname ==''):
427: logging.debug("uploadatffinallythread add to basket %s"%basketname)
428: self.result="<p>Add to basket</p>"+self.result
429: basketId=ctx2.basketContainer.getBasketIdfromName(basketname)
430:
431: if not basketId: # create new basket
432: logging.debug("uploadatffinallythread create basket %s"%basketname)
433: self.result="<p>Create a new basket</p>"+self.result
434: ob=ctx2.basketContainer.addBasket(basketname)
435: basketId=ob.getId()
436: basket=getattr(ctx2.basketContainer,str(basketId))
437: ids=os.listdir(SESSION['tmpdir'])
438: #logging.debug("should add:"+repr(ids))
439: basket.addObjects(ids,deleteOld=True,username=str(username))
440:
441: logging.debug("uploadatffinallythread uploadfinally done")
442:
443: if RESPONSE is not None:
444: RESPONSE.redirect(self.aq_parent.absolute_url())
445:
446: return True
447:
448: class tmpStore(SimpleItem):
449: """simple item"""
450: meta_type="cdli_upload"
451:
452: def __init__(self,id):
453: """init tmp"""
454: self.id=id
455:
456: class uploadATFThread(Thread):
457: """class for checking the files befor uploading"""
458:
459: def __init__(self):
460: """initialise"""
461:
462: self.continueVar=True
463: self.returnValue=None
464:
465: Thread.__init__(self)
466:
467:
468: def set(self,upload,basketId,username,idTmp,serverport="8080"):
469: """set start values for the thread"""
470: self.result=""
471: self.upload=upload
472: self.basketId=basketId
473: self.username=username
474: self.serverport=serverport
475: self.idTmp=idTmp
476:
477: def __call__(self):
478: """call method """
479: self.run()
480: return True
481:
482: def getContext(self, app,serverport="8080"):
483: """get the context within the ZODB"""
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):
494: idTmp=self.idTmp
495: self.result=""
496: #find context within ZODB
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)
502: logging.info("run intern")
503: try:
504: logging.info("created: %s"%idTmp)
505: ctx.temp_folder._setObject(idTmp,tmpStore(idTmp))
506: except:
507: logging.error("thread upload: %s %s"%sys.exc_info()[0:2])
508:
509: logging.info("call thread intern")
510: self.uploadATFThread(ctx,self.upload,idTmp,self.basketId)
511:
512: #ctx.cdliRoot.cdli_main.tmpStore2[self.getName()[0:]]=self.returnValue
513:
514:
515: transaction.get().commit()
516:
517: conn.close()
518:
519: return getattr(ctx.temp_folder,idTmp)
520:
521: def getResult(self):
522: """method for accessing result"""
523: return self.result
524:
525: def uploadATFThread(self,ctx,upload,idTmp,basketId=0):
526: """upload an atf file"""
527: #TODO: add comments
528: #TODO: finish uploadATF
529:
530: stObj=getattr(ctx.temp_folder,idTmp)
531: logging.info("start, upload thread")
532: self.result="<html><body><h2>I got your file, start now to split it into single atf-files!</h2><p>"
533:
534: #make sure that id is a string and not an integer
535: basketId=str(basketId)
536:
537: #TODO: make this configurable, at the moment, rootFolder for cdli has to be cdliRoot
538: ctx2=ctx.cdliRoot
539:
540: #get temporary file for staging the downloaded and splitted files
541: dir=mkdtemp()
542:
543:
544: changed=[] # changed files
545: errors=[] # files with errors
546: lockerrors=[] # files with errors
547:
548: newPs=[] # new p filed
549: psNotInCatalog=[] # files not in the catalog
550:
551: #split the uploadedd atf file
552: basketNameFromFile, numberOfFiles=splitatf(upload,dir,ext=self)
553:
554: #find basketId if not set
555:
556: #get active abaket
557: if basketId == '0':
558: basketObj=ctx2.basketContainer.getActiveBasket()
559: if basketObj:
560: basketId=basketObj.getId()
561:
562: #if there is no active basket and no basketid given, id is empty, else get besketname and length
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:
570: logging.info("got the file, upload thread")
571: self.result+="""<html><body><h2>I got the files</h2><
572: p>I am computing the differences to the exisiting files</p>"""
573:
574: #start to check the files
575: for fn in os.listdir(dir):
576:
577: self.result="<p>process:%s</p>"%fn+self.result
578:
579: # check if file is in the catalog
580: #TODO: checkCatalog is not implemented yet
581: if ctx2.cdli_main.checkCatalog(fn):
582: psNotInCatalog.append(fn)
583:
584: #check if p-file already at the server
585: founds=ctx2.CDLICatalog.search({'title':fn})
586:
587: #if not than add filename to the list of newfiles
588:
589: data=file(os.path.join(dir,fn)).read()
590: status,msg=checkFile(fn,data,dir)
591: #status=True
592:
593:
594: if not status: # error
595: errors.append((fn,msg))
596:
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))):
607: lockerrors.append((fn,str(obj.lockedBy)))
608: else:
609:
610: diffs=obj.diff(data)
611: if diffs[0]>0:
612: changed.append((obj,diffs)) #hochladen
613:
614: #ready, set the returnValues
615: self.result+="<h3>Done</h3></body></html>"
616:
617: stObj.returnValue={}
618:
619: stObj.returnValue['errors']=errors
620:
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
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]
632: stObj.returnValue['lockerrors']=[x for x in lockerrors]
633: self.returnValue=True
634: #ctx2.cdli_main.setTemp('v_uploadATF_returnValue',True)
635:
636:
637: class CDLIBasketContainer(OrderedFolder):
638: """contains the baskets"""
639:
640:
641: security=ClassSecurityInfo()
642: meta_type="CDLIBasketContainer"
643:
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:
653: ob=getattr(self,basketId).getContent() #get the content of a basket
654:
655: ret=[x[0].split(".")[0] for x in ob]
656:
657: return ret
658:
659: security.declareProtected('manage','getBasketAsOneFile')
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()
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:
677: if current=="no": #version as they are in the basket
678: cur= obj.getVersionNr(versionNr)
679: ret+=str(cur.getData())+"\n"
680: elif current=="yes":
681: #search current object
682: #logging.debug("current: %s"%object[1].getId().split(".")[0])
683: obj.getData()
684: return ret
685:
686: security.declareProtected('manage','upDateBaskets')
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:
695: security.declareProtected('manage','deleteBaskets')
696: def deleteBaskets(self,ids=None):
697: """delete baskets, i.e. move them into trash folder"""
698:
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)
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]
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:
720: cut=self.manage_cutObjects(ids)
721: trash.manage_pasteObjects(cut)
722: return None
723: security.declareProtected('manage','manageBaskets')
724: def manageBaskets(self,submit,ids=None,basket1="",basket2="",joinBasket="",subtractBasket="",REQUEST=None,RESPONSE=None):
725: """manage baskets, delete or copy"""
726: if submit=="delete":
727: ret= self.deleteBaskets(ids)
728: if ret:
729: return ret
730: elif submit=="join":
731: flag,msg=self.joinBasket(joinBasket, ids)
732: logging.info("joining %s %s"%(flag,msg))
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:
738: elif submit=="subtract":
739: logging.info("BBBb %s %s"%(basket1,basket2))
740: flag,msg=self.subtractBasket(subtractBasket, basket1,basket2)
741: logging.info("subtract %s %s"%(flag,msg))
742:
743: if RESPONSE:
744: RESPONSE.redirect(self.absolute_url())
745:
746: security.declareProtected('View','getBasketIdfromName')
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
755:
756: security.declareProtected('manage','uploadBasket_html')
757:
758: def uploadBasket_html(self,basketId='0'):
759: """upload an atf file, html form"""
760:
761:
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:
772: security.declareProtected('manage','index_html')
773: def index_html(self):
774: """stanadard ansicht"""
775:
776:
777:
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:
794:
795: def getBasketsId(self):
796: """get all baskets als klartext"""
797:
798: ret=""
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"
805: return ret
806:
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)
862:
863: return baskets
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: """
876:
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:
885:
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):
913: """join two baskets
914: @param newbasket: name of the new basket
915: @param oldbaskets: list of baskets to be joined
916: """
917: if oldBaskets is None:
918: return False, "No Baskets selected!"
919:
920: try:
921: newB=self.addBasket(newBasket)
922: except:
923: return False, "cannot create the new basket"
924:
925: newBasketContent={}
926:
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:
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:
956: def setActiveBasket(self,basketId,REQUEST=None):
957: """store active basketId in a cookie"""
958: self.REQUEST.RESPONSE.setCookie("CDLIActiveBasket",basketId,path="/")
959: try:
960: qs=cgi.parse_qs(REQUEST['QUERY_STRING'])
961: del(qs['basketId'])
962: except:
963: qs={}
964: if REQUEST:
965: REQUEST.RESPONSE.redirect(REQUEST['URL1']+'?'+urllib.urlencode(qs))
966:
967: def getActiveBasket(self):
968: """get active basket from cookie"""
969:
970: id= self.REQUEST.cookies.get('CDLIActiveBasket',None)
971: if id:
972: obj=getattr(self,str(id),None)
973: else:
974: obj=None
975: return obj
976:
977: def getActualUserName(self):
978: """get name of the actualuser"""
979: return str(self.REQUEST['AUTHENTICATED_USER'])
980:
981: security.declareProtected('manage','addBasket')
982: def addBasket(self,newBasketName):
983: """add a new basket"""
984:
985: ob=manage_addCDLIBasket(self,newBasketName)
986: return ob
987:
988: def storeInBasket(self,submit,ids=None,newBasketName=None,fromFileList=None,RESPONSE=None,REQUEST=None):
989: """store it"""
990: if not ids:
991: ids=self.REQUEST.SESSION['fileIds']
992:
993: if (type(ids) is not ListType) and (not isinstance(ids,Set)):
994: ids=[ids]
995:
996: if isinstance(ids,Set):
997: ids=list(ids)
998:
999: if (submit.lower()=="store in new basket") or (submit.lower()=="new basket"):
1000: basketRet=self.addBasket(newBasketName)
1001: self.setActiveBasket(basketRet.getId())
1002: basket=getattr(self,basketRet.getId())
1003: elif (submit.lower()=="store in active basket") or (submit.lower()=="active basket"):
1004: basket=self.getActiveBasket()
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:
1011:
1012: return self.cdli_main.findObjectsFromList(list=ids,basketName=basket.title,numberOfObjects=added)
1013:
1014: if RESPONSE:
1015:
1016: RESPONSE.redirect(back)
1017:
1018: return True
1019:
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:
1034: class CDLIBasket(Folder,CatalogAware):
1035: """basket"""
1036:
1037: meta_type="CDLIBasket"
1038: default_catalog="CDLIBasketCatalog"
1039:
1040: def searchInBasket(self,indexName,searchStr,regExp=False):
1041: """searchInBasket"""
1042:
1043: lst=self.searchInLineIndexDocs(indexName,searchStr,uniq=True,regExp=regExp) #TODO: fix this
1044: ret={}
1045:
1046: lv=self.getLastVersion()
1047:
1048:
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):
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:
1077: def getFile(self,obj):
1078: return obj[1]
1079:
1080: def getFileLastVersion(self,obj):
1081: return obj[0]
1082:
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:
1088:
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):
1108: """teste ob im basket die aktuelle version ist"""
1109: try:
1110: #logging.debug("isActual:"+repr(obj))
1111: actualNo=obj[1].getLastVersion().getVersionNumber()
1112: storedNo=obj[0].getVersionNumber()
1113:
1114:
1115: #actualNo=self.getFileObjectLastVersion(obj.getId()).getVersionNumber()
1116:
1117: #if len(founds)>0 and founds[0].getObject().aq_parent.getId()==".trash":
1118: # return False, -1
1119:
1120: if actualNo==storedNo:
1121: return True , 0
1122: else:
1123: return False, actualNo
1124: except:
1125: logging.error( """is actual: %s (%s %s)"""%(repr(obj),sys.exc_info()[0],sys.exc_info()[1]))
1126:
1127: return False, -1
1128:
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:
1151: def getActualUserName(self):
1152: """get name of the actualuser"""
1153:
1154: return str(self.REQUEST['AUTHENTICATED_USER'])
1155:
1156:
1157: def getLastVersion(self):
1158: """hole letzte version"""
1159:
1160: ids=[]
1161: idsTmp= self.objectIds()
1162: for x in idsTmp:
1163: try:
1164: ids.append(int(x))
1165: except:
1166: pass
1167: ids.sort()
1168:
1169: if len(ids)==0:
1170: return None
1171: else:
1172: ob=getattr(self,str(ids[-1]))
1173:
1174:
1175: return ob
1176:
1177: def getVersions(self):
1178: """get versions"""
1179: versions=self.ZopeFind(self,obj_metatypes=["CDLIBasketVersion"])
1180: return versions
1181:
1182:
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()
1189: oldContent=lastVersion.content.getContent()
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:
1212: obj=self._getOb(ob.getId())
1213: if RESPONSE:
1214:
1215: RESPONSE.redirect(obj.absolute_url())
1216:
1217: return obj
1218:
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:
1269: def addObjects(self,ids,deleteOld=None,username=None):
1270: """generate a new version of the basket with objects added"""
1271:
1272: def swap(x):
1273: return (x[1],x[0])
1274:
1275: logging.info("add to basket (%s)"%(repr(ids)))
1276: logging.info("add to basket (%s)"%(self.getId()))
1277: lastVersion=self.getLastVersion()
1278:
1279: if lastVersion is None:
1280: oldContent=[]
1281: else:
1282: oldContent=lastVersion.content.getContent()
1283:
1284: if deleteOld:
1285: oldContent=[]
1286:
1287: added=0
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:
1301: hash = md5.new(repr(makelist(ids))).hexdigest() # erzeuge hash als identification
1302: #logging.debug("JJJJJJJ:"+repr(self.makelist(ids)))
1303:
1304: retrieved = self.CDLICache.retrieve(hash)
1305: if retrieved:
1306: newContent=Set(map(swap,retrieved))
1307: else:
1308: newContent=Set([(self.getFileObjectLastVersion(x),self.getFileObject(x)) for x in ids])
1309:
1310:
1311:
1312: #remove all Elements which are not stored
1313: if (None,None) in newContent:
1314: newContent.remove((None,None))
1315: content=Set(oldContent).union(newContent)
1316: added = len(content)-len(oldContent)
1317: if not username:
1318: user=self.getActualUserName()
1319: else:
1320: user = username
1321:
1322: #logging.debug("content:"+repr(list(content)))
1323: ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=list(content))
1324: logging.info("add to basket (%s) done"%(self.getId()))
1325: return added
1326:
1327:
1328:
1329: def getContent(self):
1330: """print content"""
1331: ret=[]
1332:
1333: lv=self.getLastVersion()
1334: #for obj in lv.content.getContent():
1335: #logging.info("XXXXXXXXXX %s"%repr(obj))
1336: # ret.append((obj[1].getId(),obj[0].versionNumber))
1337:
1338: return lv
1339:
1340: def getContentIds(self):
1341: """print basket content"""
1342: ret=[]
1343: lv=self.getLastVersion()
1344: for obj in lv.content.getContent():
1345: ret.append((obj[0].getId(),obj[1].getId()))
1346:
1347:
1348: return lv.getComment(),lv.getUser(),lv.getTime(),ret
1349:
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:
1357: def deleteObjects(self,ids,RESPONSE=None,REQUEST=None):
1358: """delete objects"""
1359:
1360: if type(ids) is not ListType:
1361: ids=[ids]
1362:
1363: lastVersion=self.getLastVersion()
1364: oldContent=lastVersion.content.getContent()
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())
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:
1398: class CDLIBasketVersion(Implicit,Persistent,Folder):
1399: """version of a basket"""
1400:
1401: meta_type="CDLIBasketVersion"
1402: security=ClassSecurityInfo()
1403:
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:
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:
1422: if not self.isActual(obj[0],obj[1])[0]:
1423: return True
1424: return False
1425:
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:
1441: security.declareProtected('manage','downloadObjectsAsOneFile')
1442: def downloadObjectsAsOneFile(self,lock=None,procedure=None,REQUEST=None,check="yes",current="no"):
1443: """download all selected files in one file"""
1444:
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!"""
1447:
1448:
1449: if (check=="yes") and self.containsNonActualFiles():
1450: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadObjectAsOneFile_check.zpt')).__of__(self)
1451:
1452: return pt(lock=lock)
1453:
1454: else:
1455:
1456: return self.downloadObjectsAsOneFileFinally(lock=lock,procedure=procedure,REQUEST=REQUEST,current="no")
1457:
1458: def downloadObjectsAsOneFileFinally(self,lock=None,procedure=None,REQUEST=None,current="no",repeat=None):
1459: """print do the download"""
1460:
1461:
1462: ret=""
1463: lockedObjects={}
1464:
1465:
1466:
1467: if lock:
1468: logging.debug("------lock:"+repr(lock))
1469: if str(self.REQUEST['AUTHENTICATED_USER'])=='Anonymous User':
1470:
1471: return "please login first"
1472:
1473: #check if a locked object exist in the basket.
1474: lockedObjects={}
1475: for object in self.content.getContent():
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)
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)
1487:
1488:
1489: return pt()
1490:
1491: elif not procedure: #keine fails gesperrt dann alle donwloaden
1492: procedure="downloadAll"
1493:
1494:
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))
1508:
1509: if isinstance(self,CDLIBasketVersion):
1510: obj=self
1511: else:
1512: obj=self.aq_parent
1513: logging.debug("dwonloadfinally2:"+repr(obj))
1514: logging.debug("dwonloadfinally2:"+repr(obj.aq_parent))
1515:
1516: obj2=obj.aq_parent
1517: if not isinstance(obj2,CDLIBasket):
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:
1525:
1526: if lock:
1527: logging.debug("-----start locking")
1528: for object in self.content.getContent():
1529: obj=self.ctx.getFileObject(object[0])
1530: if obj.lockedBy =='':
1531: obj.lockedBy=self.REQUEST['AUTHENTICATED_USER']
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)
1536:
1537: self._v_downloadBasket[threadName].start()
1538:
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:
1547: return pt(txt=self.absolute_url()+'/downloadObjectsAsOneFileFinally',threadName=threadName,
1548: counter=self._v_downloadBasket[threadName].getCounter(),
1549: number=self._v_downloadBasket[threadName].getNumberOfFiles())
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]()
1566:
1567: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadBasketWait.zpt')).__of__(self)
1568: return pt(txt=self.absolute_url()+'/downloadObjectsAsOneFileFinally',threadName=threadName,
1569: counter=self._v_downloadBasket[threadName].getCounter(),
1570: number=self._v_downloadBasket[threadName].getNumberOfFiles())
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]
1582: lockedFiles=self.basketContainer.resultLockedHash[threadName]
1583:
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()
1591:
1592:
1593:
1594: #write basketname to header of atf file
1595:
1596:
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)
1601:
1602: ret="#basket: %s\n"%basket_name
1603: self.REQUEST.RESPONSE.write(ret)
1604:
1605: for fileName in files:
1606: logging.debug("download: %s"%fileName)
1607: try:
1608: self.REQUEST.RESPONSE.write(file(fileName).read())
1609: except:
1610: logging.error("downloadasonefile: cannot read %s"%fileName)
1611:
1612:
1613: self.REQUEST.RESPONSE.write("\n# locked files\n")
1614: for fileName in lockedFiles:
1615: self.REQUEST.RESPONSE.write("# %s by %s\n"%fileName)
1616:
1617: self.REQUEST.RESPONSE.write("# locked files end\n")
1618:
1619: del self.basketContainer.resultHash[threadName]
1620: del self.basketContainer.resultLockedHash[threadName]
1621:
1622: def numberOfItems(self):
1623: """return anzahl der elemente im basket"""
1624: return self.content.numberOfItems()
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"""
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
1646:
1647:
1648: def __init__(self,id,user,comment="",basketContent=[]):
1649: """ init a basket version"""
1650: self.id=id
1651: self.comment=comment
1652: self._setObject('content',BasketContent(basketContent))
1653: #self.basketContent=basketContent[0:]a
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:
1665: security.declareProtected('manage','index_html')
1666: def index_html(self):
1667: """view the basket"""
1668: logging.debug("start index_html - Basket version")
1669: if self.REQUEST.get('change',False):
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
1673: logging.debug("start index_html - Basket version:template")
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"""
1679:
1680: founds=self.CDLICatalog.search({'title':result})
1681: if len(founds)>0:
1682: return founds[0].getObject().getLastVersion().absolute_url()
1683:
1684: else: #assume version number
1685: splitted=result.split("_")
1686: founds=self.CDLICatalog.search({'title':splitted[1]})
1687: return founds[0].getObject().getLastVersion().absolute_url()+'/'+result
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:
1709: class CDLIFileObject(CatalogAware,extVersionedFileObject):
1710: """CDLI file object"""
1711:
1712: meta_type="CDLI File Object"
1713: default_catalog='CDLIObjectsCatalog'
1714:
1715: security=ClassSecurityInfo()
1716:
1717: security.declareProtected('manage','index_html')
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:
1725: def PrincipiaSearchSource(self):
1726: """Return cataloguable key for ourselves."""
1727: return str(self)
1728:
1729: def setAuthor(self, author):
1730: """change the author"""
1731: self.author = author
1732:
1733: def makeThisVersionCurrent_html(self):
1734: """form for mthis version current"""
1735:
1736: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','makeThisVersionCurrent.zpt')).__of__(self)
1737: return pt()
1738:
1739: security.declarePublic('makeThisVersionCurrent')
1740: def makeThisVersionCurrent(self,comment,author,RESPONSE=None):
1741: """copy this version to current"""
1742: parent=self.aq_parent
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())
1746:
1747: #if RESPONSE is not None:
1748: # RESPONSE.redirect(self.aq_parent.absolute_url()+'/history')
1749:
1750: return True
1751:
1752: def getFormattedData(self):
1753: """fromat text"""
1754: data=self.getData()
1755: # return re.sub("\s\#lem"," #lem",data) #remove return vor #lem
1756: return re.sub("#lem"," #lem",data) #remove return vor #lem
1757:
1758:
1759: security.declarePublic('getPNumber')
1760: def getPNumber(self):
1761: """get the pnumber"""
1762: try:
1763: txt=re.match("&[Pp](\d*)\s*=([^\r\n]*)",self.getData()[0:])
1764: except:
1765: txt=self.getData()[0:]
1766:
1767: return "ERROR"
1768: try:
1769: return "P"+txt.group(1)
1770: except:
1771: return "ERROR"
1772:
1773: security.declarePublic('getDesignation')
1774: def getDesignation(self):
1775: """get the designation out of the file"""
1776: try:
1777: txt=re.match("&[Pp](\d*)\s*=([^\r\n]*)",self.getData()[0:])
1778: except:
1779: txt=self.getData()[0:]
1780:
1781: return "ERROR"
1782: try:
1783: return txt.group(2)
1784: except:
1785: return "ERROR"
1786:
1787:
1788: manage_addCDLIFileObjectForm=DTMLFile('dtml/fileAdd', globals(),Kind='CDLIFileObject',kind='CDLIFileObject', version='1')
1789:
1790: def manage_addCDLIFileObject(self,id,vC='',author='', file='',title='',versionNumber=0,
1791: precondition='', content_type='',
1792: from_tmp=False,REQUEST=None):
1793: """Add a new File object.
1794: Creates a new File object 'id' with the contents of 'file'"""
1795:
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:
1806: self._setObject(id, CDLIFileObject(id,title,versionNumber=versionNumber,versionComment=vC,time=time.localtime(),author=author))
1807: fob = self._getOb(id)
1808:
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.
1811:
1812: if file and not from_tmp:
1813: fob.manage_upload(file)
1814: elif file and from_tmp:
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
1817: if content_type:
1818: fob.content_type=content_type
1819:
1820: #logging.debug("manage_add: lastversion=%s"%self.getData())
1821: logging.debug("reindex1: %s in %s"%(repr(self),repr(self.default_catalog)))
1822: self.reindex_object()
1823: #logging.debug("manage_add: fob_data=%s"%fob.getData())
1824: logging.debug("reindex2: %s in %s"%(repr(fob), repr(fob.default_catalog)))
1825: fob.index_object()
1826:
1827: self.CDLIRoot.updateOrAddToFileBTree(ob)
1828: if REQUEST is not None:
1829: REQUEST['RESPONSE'].redirect(self.absolute_url()+'/manage_main')
1830:
1831:
1832: class CDLIFile(extVersionedFile,CatalogAware):
1833: """CDLI file"""
1834:
1835: security=ClassSecurityInfo()
1836: meta_type="CDLI file"
1837: content_meta_type = ["CDLI File Object"]
1838:
1839: default_catalog='CDLICatalog'
1840:
1841: security.declareProtected('manage','index_html')
1842:
1843: def getLastVersionData(self):
1844: """get last version data"""
1845: return self.getData()
1846:
1847: def getLastVersionFormattedData(self):
1848: """get last version data"""
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]
1855:
1856: #security.declarePublic('history')
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:
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:
1880:
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
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()})]
1899:
1900:
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:
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:
1918: def manage_addCDLIFileObject(self,id,vC,author,
1919: file='',title='',
1920: precondition='',
1921: content_type='',
1922: changeName='no',newName='',
1923: come_from=None,
1924: from_tmp=False,RESPONSE=None):
1925: """add"""
1926:
1927: try: #TODO: der ganze vC unsinn muss ueberarbeitet werden
1928: vC=self.REQUEST['vC']
1929: except:
1930: pass
1931:
1932: ob = self.addContentObject(id, vC, author, file, title, changeName=changeName, newName=newName, from_tmp=from_tmp,
1933: precondition=precondition, content_type=content_type)
1934:
1935: try:
1936: #FIXME: wozu ist das gut?
1937: self.REQUEST.SESSION['objID_parent']=self.getId()
1938: except:
1939: pass
1940:
1941: #self.cdliRoot.updateOrAddToFileBTree(self)# now update the object in the cache
1942:
1943:
1944: if RESPONSE:
1945: if ob.getSize()==0:
1946: self.REQUEST.SESSION['objID']=ob.getId()
1947: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','errorUploadFile')).__of__(self)
1948: return pt()
1949: else:
1950: if come_from and (come_from!=""):
1951: RESPONSE.redirect(come_from+"?change="+self.getId())
1952: else:
1953: RESPONSE.redirect(self.REQUEST['URL2']+'?uploaded=%s'%self.title)
1954: else:
1955: return ob
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)
1966:
1967: tryToggle=True
1968: tryCount=0
1969:
1970: self._setObject(id,newObj)
1971: getattr(self,id).reindex_object()
1972:
1973: if RESPONSE is not None:
1974: RESPONSE.redirect('manage_main')
1975:
1976:
1977: def checkUTF8(data):
1978: """check utf 8"""
1979: try:
1980: data.encode('utf-8')
1981: return True
1982: except:
1983: return False
1984:
1985:
1986: def checkFile(filename,data,folder):
1987: """check the files"""
1988: # first check the file name
1989: fn=filename.split(".") # no extension
1990:
1991: if not fn[0][0]=="P":
1992: return False,"P missing in the filename"
1993: elif len(fn[0])!=7:
1994: return False,"P number has not the right length 6"
1995: elif not checkUTF8(data):
1996: return False,"not utf-8"
1997: else:
1998: return True,""
1999:
2000:
2001: def splitatf(fh,dir=None,ext=None):
2002: """split it"""
2003: ret=None
2004: nf=None
2005: i=0
2006:
2007: #ROC: why split \n first and then \r???
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:
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:
2037:
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()
2048: except:
2049: pass
2050:
2051: if not((type(fh) is StringType) or (type(fh) is UnicodeType)):
2052: fh.close()
2053: return ret,len(os.listdir(dir))
2054:
2055:
2056: class CDLIFileFolder(extVersionedFileFolder):
2057: """CDLI File Folder"""
2058:
2059: security=ClassSecurityInfo()
2060: meta_type="CDLI Folder"
2061: file_meta_type=['CDLI file']
2062: folder_meta_type=['CDLI Folder']
2063:
2064: file_catalog='CDLICatalog'
2065:
2066: #downloadCounter=0 # counts how many download for all files currently run, be mehr als 5 wird verweigert.
2067: tmpStore2={}
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:
2074: def setTemp(self,name,value):
2075: """set tmp"""
2076:
2077: setattr(self,name,value)
2078:
2079: deleteFileForm = PageTemplateFile("zpt/doDeleteFile", globals())
2080:
2081: def delete(self,ids,REQUEST=None):
2082: """delete these files"""
2083: if type(ids) is not ListType:
2084: ids=[ids]
2085:
2086: self.manage_delObjects(ids)
2087:
2088: if REQUEST is not None:
2089: return self.index_html()
2090:
2091:
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:
2098: founds=self.CDLICatalog.search({'title':searchStr})
2099:
2100: for found in founds:
2101: lastVersion=found.getObject().getContentObject()
2102: ret.append((found.getId,lastVersion))
2103:
2104: return ret
2105:
2106: def getFile(self,fn):
2107: """get the content of the file fn"""
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 ""
2116: else:
2117: obj = self[fn].getContentObject()
2118:
2119: return obj.getData()[0:]
2120:
2121:
2122: def checkCatalog(self,fn):
2123: """check if fn is in the catalog"""
2124: #TODO add checkCatalog
2125:
2126:
2127: def findObjectsFromListWithVersion(self,list,author=None):
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:
2136: return pt(search=list,author=author)
2137:
2138:
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:
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:
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):
2154: """findObjectsFromList (, TAB oder LINE separated)"""
2155:
2156: logging.debug("start: findObjectsFromList")
2157: #logging.debug("start: findObjectsFromList"+repr(list))
2158:
2159:
2160: if upload: # list from file upload
2161: txt=upload.read()
2162:
2163: if enterList:
2164: txt=enterList
2165:
2166: if upload or enterList:
2167: txt=txt.replace(",","\n")
2168: txt=txt.replace("\t","\n")
2169: txt=txt.replace("\r","\n")
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)
2179:
2180: pt=getattr(self,'filelist.html')
2181: self.REQUEST.SESSION['searchList']=ids
2182: return pt(search=ids)
2183:
2184: if basketName:
2185: #TODO: get rid of one of these..
2186:
2187: pt=getattr(self,'filelist.html')
2188: return pt(basketName=basketName,numberOfObjects=numberOfObjects)
2189:
2190:
2191: result =self.CDLICache.retrieve(hash)
2192: if result:
2193: logging.debug("give result from storage2")
2194: return hash,result
2195:
2196: if list is not None: # got already a list
2197:
2198: logging.debug(" ----List version")
2199: ret=[]
2200: fileTree=Set()
2201:
2202: for fileId in list:
2203:
2204: if fileId.find("*")>-1: #check for wildcards
2205: self.expandFile(fileId,fileTree)
2206:
2207: elif len(fileId.split("."))==1:
2208: fileId=fileId+".atf"
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)
2215:
2216:
2217:
2218: ids = fileTree & self.v_file_ids
2219: #self.REQUEST.SESSION['fileIds']=ids#store fieldIds in session for further usage
2220: l=makelist(fileTree)[0:]
2221: #logging.debug("l-list:"+repr(l))
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:
2226:
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 ?
2230:
2231: #logging.debug("Hash:"+repr(hash))
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
2240:
2241: #TODO: get rid of one of these..
2242: #ids=[x.getObject().getId() for x in ret]
2243: ret=[(self.getFileObject(x),self.getFileObjectLastVersion(x)) for x in ids]
2244:
2245: #self.REQUEST.SESSION['fileIds']=ids#store fieldIds in session for further usage
2246: #self.REQUEST.SESSION['searchList']=self.REQUEST.SESSION['fileIds']
2247:
2248: if display:
2249: pt=getattr(self,'filelist.html')
2250:
2251: return pt(search=ids)
2252: else:
2253: #self.REQUEST.SESSION['hash'] = ret # store in session
2254:
2255: #logging.debug("HHHHHHNEU:"+repr(self.makelist(ids)))
2256: #logging.debug("HHHHHHNEU:"+repr(hash))
2257: self.CDLICache.store(hash,ret)
2258:
2259: if returnHash == True:
2260: return hash,ret
2261: return ret
2262:
2263:
2264:
2265: if start:
2266: RESPONSE.redirect("filelist.html?start:int="+str(start))
2267:
2268: security.declareProtected('Manage','createAllFilesAsSingleFile')
2269: def createAllFilesAsSingleFile(self,RESPONSE=None):
2270: """download all files"""
2271:
2272: def sortF(x,y):
2273: return cmp(x[0],y[0])
2274:
2275: catalog=getattr(self,self.file_catalog)
2276: #tf,tfilename=mkstemp()
2277: if not hasattr(self.temp_folder,'downloadCounter'):
2278: self.temp_folder.downloadCounter=0
2279:
2280: if getattr(self.temp_folder,'downloadCounter',0) > 5:
2281: return """I am sorry, currently the server has to many requests for downloads, please come back later!"""
2282:
2283: self.temp_folder.downloadCounter+=1
2284: self._p_changed=1
2285: transaction.get().commit()
2286:
2287: list=[(x.getId,x) for x in catalog()]
2288: list.sort(sortF)
2289:
2290:
2291:
2292: RESPONSE.setHeader("Content-Disposition","""attachement; filename=%s"""%"all.atf")
2293: RESPONSE.setHeader("Content-Type","application/octet-stream")
2294: tmp=""
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:
2302: RESPONSE.write(obj.getData()[0:])
2303: RESPONSE.write("\n")
2304: self.temp_folder.downloadCounter-=1
2305: self._p_changed=1
2306: transaction.get().commit()
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:
2322: if self.aq_parent.meta_type in self.folder_meta_type:
2323: return True
2324: else:
2325: return False
2326:
2327: def getFolders(self):
2328: """get all subfolders"""
2329: ret=[]
2330: folders=self.ZopeFind(self,obj_metatypes=self.folder_meta_type)
2331: for folder in folders:
2332: ret.append((folder[1],
2333: len(self.ZopeFind(folder[1],obj_metatypes=self.folder_meta_type)),
2334: len(self.ZopeFind(folder[1],obj_metatypes=self.file_meta_type))
2335: ))
2336: return ret
2337:
2338:
2339: security.declareProtected('manage','index_html')
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:
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"
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:
2394:
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:
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:
2452: def getFileObject(self,fileId):
2453: """get an object"""
2454: x=self.v_files.get(fileId)
2455: #logging.debug(x)
2456: return x
2457:
2458: def getFileObjectLastVersion(self,fileId):
2459: """get an object"""
2460: x=self.v_files_lastVersion.get(fileId)
2461: #logging.debug("lastVersion: "+repr(x))
2462: return x
2463:
2464: def showFileIds(self):
2465: """showIds"""
2466: return self.v_file_ids
2467:
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:
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:
2500: def deleteFiles(self,ids):
2501: """delete files"""
2502: for id in ids:
2503: founds=self.CDLICatalog.search({'title':id.split(".")[0]})
2504: if founds:
2505: logging.debug("deleting %s"%founds)
2506: folder=founds[0].getObject().aq_parent #get the parent folder of the object
2507: logging.debug("deleting from %s"%folder)
2508: cut=folder.delete([founds[0].getId]) #cut it out
2509:
2510:
2511:
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 ""
2534:
2535: return f[0].getObject().getData()
2536:
2537:
2538: def showFile(self,fileId,wholePage=False):
2539: """show a file
2540: @param fileId: P-Number of the document to be displayed
2541: """
2542: f=getattr(self, self.file_catalog).search({'textid':fileId})
2543: if not f:
2544: return ""
2545:
2546: if wholePage:
2547: logging.debug("show whole page")
2548: return f[0].getObject().getContentObject().view()
2549: else:
2550: return f[0].getObject().getLastVersionFormattedData()
2551:
2552:
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))
2556:
2557: file = formatAtfFullLineNum(self.getFile(fileId))
2558: ret=[]
2559:
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():
2574: for word in wordlist:
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:
2581: return ret
2582:
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))
2590:
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
2602: ret=[]
2603:
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))
2617:
2618: for line in file.splitlines():
2619: line = unicodify(line)
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:
2665:
2666:
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:
2675:
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:
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:
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:
2701:
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()
2707:
2708: if un and un !="":
2709: ret.append((f[0],un))
2710:
2711: return ret
2712:
2713:
2714: def getChangesByAuthor(self,author,n=100):
2715: """getChangesByAuthor"""
2716: zcat=self.CDLIObjectsCatalog
2717: res=zcat({'lastEditor':author,
2718: 'sort_on':'getTime',
2719: 'sort_order':'descending',
2720: 'sort_limit':n})[:n ]
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:
2736: return self.cdli_main.findObjectsFromListWithVersion(list=tmp.values(),author=author)
2737:
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:
2752: def refreshTxt(self,txt="",threadName=None):
2753: """txt fuer refresh"""
2754:
2755: return """ 2;url=%s?repeat=%s """%(self.absolute_url()+txt,threadName)
2756:
2757: def refreshTxtBasket(self,txt="",threadName=None):
2758: """txt fuer refresh"""
2759:
2760: return """ 2;url=%s?repeat=%s """%(txt,threadName)
2761:
2762:
2763: def getResult(self,threadName=None):
2764: """result of thread"""
2765: try:
2766: return self._v_uploadATF[threadName].getResult()
2767: except:
2768: return "One moment, please"
2769:
2770:
2771: def checkThreads(self):
2772: """check threads"""
2773: ret="<html><body>"
2774: for thread in threading.enumerate():
2775: ret+="<p>%s (%s): %s</p>"%(repr(thread),thread.getName(),thread.isAlive())
2776:
2777: return ret
2778:
2779:
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:
2809: def uploadATF(self,repeat=None,upload=None,basketId=0,RESPONSE=None):
2810: """upload an atf file / basket file"""
2811: #self._v_uploadATF.returnValue=None
2812:
2813: #generate an random id for the upload thread
2814: from random import randint
2815: if (not self.REQUEST.SESSION.get('idTmp',None)):
2816:
2817: idTmp=str(randint(0,1000000000))
2818: self.REQUEST.SESSION['idTmp']=idTmp
2819: else:
2820: idTmp=self.REQUEST.SESSION.get('idTmp',None)
2821:
2822:
2823: threadName=repeat
2824: if not threadName or threadName=="":
2825: #new thread not called from the waiting page
2826: tmpVar=False
2827:
2828: thread=uploadATFThread()
2829: threadName=thread.getName()[0:]
2830: if (not hasattr(self,'_v_uploadATF')):
2831: self._v_uploadATF={}
2832:
2833: self._v_uploadATF[threadName]=thread
2834: #self._xmltrans.start()
2835: #thread=Thread(target=self._v_uploadATF)
2836: logging.info("set thread. extern")
2837: self._v_uploadATF[threadName].set(upload,basketId,self.REQUEST['AUTHENTICATED_USER'],idTmp,serverport=self.REQUEST['SERVER_PORT'])
2838: #thread.start()
2839: logging.info("start thread. extern")
2840: self._v_uploadATF[threadName].start()
2841:
2842:
2843: self.threadName=self._v_uploadATF[threadName].getName()[0:]
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)
2849: return pt(txt='/uploadATF',threadName=threadName)
2850: #_v_xmltrans.run()
2851:
2852: else:
2853: #recover thread, if lost
2854: if (not hasattr(self,'_v_uploadATF')):
2855: self._v_uploadATF={}
2856: if not self._v_uploadATF.get(threadName,None):
2857: for thread in threading.enumerate():
2858: if threadName == thread.getName():
2859: self._v_uploadATF[threadName]=thread
2860:
2861: if self._v_uploadATF.get(threadName,None) and (not self._v_uploadATF[threadName].returnValue):
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:
2870: return pt(txt='/uploadATF',threadName=threadName)
2871:
2872: else:
2873: tmp=getattr(self.temp_folder,idTmp).returnValue
2874:
2875: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadCheck.zpt')).__of__(self)
2876:
2877: return pt(changed=tmp['changed'],lockerrors=tmp['lockerrors'],errors=tmp['errors'],dir=tmp['dir'],newPs=tmp['newPs'],basketLen=tmp['basketLen'],numberOfFiles=tmp['numberOfFiles'],
2878: basketNameFromId=tmp['basketNameFromId'],basketNameFromFile=tmp['basketNameFromFile'],basketId=tmp['basketId'])
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)
2884: return pt(changed=tmp['changed'],lockerrors=tmp['lockerrors'],errors=tmp['errors'],dir=tmp['dir'],newPs=tmp['newPs'],basketLen=tmp['basketLen'],numberOfFiles=tmp['numberOfFiles'],
2885: basketNameFromId=tmp['basketNameFromId'],basketNameFromFile=tmp['basketNameFromFile'],basketId=tmp['basketId'])
2886:
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=="":
2894: thread=uploadATFfinallyThread()
2895: threadName=thread.getName()[0:]
2896:
2897: if (not hasattr(self,'_v_uploadATF')):
2898: self._v_uploadATF={}
2899:
2900:
2901: self._v_uploadATF[threadName]=thread
2902:
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'])
2906:
2907: self._v_uploadATF[threadName].start()
2908:
2909:
2910:
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:
2917: return pt(txt='/uploadATFfinally',threadName=threadName)
2918: #_v_xmltrans.run()
2919:
2920: else:
2921: #recover thread, if lost
2922: if not hasattr(self,'_v_uploadATF'):
2923: self._v_uploadATF={}
2924: if not self._v_uploadATF.get(threadName,None):
2925: for thread in threading.enumerate():
2926: if threadName == thread.getName():
2927: self._v_uploadATF[threadName]=thread
2928:
2929: if self._v_uploadATF.get(threadName,None) and (self._v_uploadATF[threadName] is not None) and (not self._v_uploadATF[threadName].end) :
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)
2936: return pt(txt='/uploadATFfinally',threadName=threadName)
2937: else:
2938:
2939:
2940: idTmp=self.REQUEST.SESSION['idTmp']
2941: stObj=getattr(self.temp_folder,idTmp)
2942: self.REQUEST.SESSION['idTmp']=None
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())
2950: if RESPONSE is not None:
2951: RESPONSE.redirect(self.absolute_url())
2952:
2953: def importFiles(self,comment="",author="" ,folderName="/Users/dwinter/atf", files=None,ext=None):
2954: """import files"""
2955: logging.debug("importFiles folderName=%s files=%s ext=%s"%(folderName,files,ext))
2956: root=self.cdli_main
2957: count=0
2958: if not files:
2959: files=os.listdir(folderName)
2960:
2961: for f in files:
2962: folder=f[0:3]
2963: f2=f[0:5]
2964:
2965: #check if main folder PXX already exists
2966: obj=self.ZopeFind(root,obj_ids=[folder])
2967: logging.debug("importFiles: folder=%s f2=%s obj=%s"%(folder,f2,obj))
2968: if ext:
2969: ext.result="<p>adding: %s </p>"%f+ext.result
2970:
2971:
2972: if not obj: # if not create it
2973: manage_addCDLIFileFolder(root,folder,folder)
2974: fobj=getattr(root,folder)
2975: #transaction.get().commit()
2976:
2977: else:
2978: fobj=obj[0][1]
2979:
2980: #check IF PYYYYY already exist
2981: obj2=fobj.ZopeFind(fobj,obj_ids=[f2])
2982: logging.debug("importFiles: fobj=%s obj2=%s"%(fobj,obj2))
2983:
2984: if not obj2:# if not create it
2985: manage_addCDLIFileFolder(fobj,f2,f2)
2986: fobj2=getattr(fobj,f2)
2987:
2988: else:
2989: fobj2=obj2[0][1]
2990:
2991: # not add the file
2992: file2=os.path.join(folderName,f)
2993: id=f
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)
2996: count+=1
2997:
2998: #now add the file to the storage
2999: ob = getattr(fobj2,f)
3000: self.cdliRoot.updateOrAddToFileBTree(ob)
3001:
3002: if count%100==0:
3003: logging.debug("importfiles: committing")
3004: transaction.get().commit()
3005:
3006: transaction.get().commit()
3007: return "ok"
3008:
3009:
3010: manage_addCDLIRootForm=DTMLFile('dtml/rootAdd', globals())
3011:
3012:
3013: def manage_addCDLIRoot(self, id, title='',
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: """
3023: ob=CDLIRoot()
3024: ob.id=str(id)
3025: ob.title=title
3026: try:
3027: self._setObject(id, ob)
3028: except:
3029: pass
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:
3043: return self.manage_main(self, REQUEST, update_menu=1)
3044:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>