Annotation of versionedFile/extVersionedFile.py, revision 1.7
1.3 dwinter 1: """actual version of the versioned file folder with external filestorage,
2: using the ExtFile Product, this version replaces externaVersionedFile.py
3: DW 11.10.2006
4: """
5:
1.1 dwinter 6: from OFS.Folder import Folder
7: from OFS.Image import File
8: from OFS.Image import cookId
9: from Globals import DTMLFile, InitializeClass,package_home
10: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
11: from AccessControl import getSecurityManager
12: from Products.PageTemplates.PageTemplate import PageTemplate
13: from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
14: from AccessControl import ClassSecurityInfo
15: from difflib import Differ
16: from pprint import pprint
17: from Products.ExtFile.ExtFile import *
18: from Products.ZCatalog.CatalogPathAwareness import CatalogAware
19:
20: try:
1.6 casties 21: from Products.ImageArchive.ImageArchive import manage_AddImageZogiLib
1.1 dwinter 22: except:
1.6 casties 23: print "no images"
1.1 dwinter 24:
25: from threading import Thread
26: import shutil
27: import tempfile
28: import os.path
29: import urllib
1.5 casties 30: import time
31: import logging
1.1 dwinter 32:
33: try:
34: from Products.ECHO_content.ECHO_collection import ECHO_basis
35: except:
36: print "ECHO Elements not imported"
37: class ECHO_basis:
1.6 casties 38: """leer"""
39: manage_options=()
1.1 dwinter 40:
41:
42: def sortv(x,y):
43: return cmp(x[0],y[0])
1.7 ! casties 44:
1.1 dwinter 45: tdir = "/tmp/downloadVersionedFiles"
46:
47: class generateDownloadZip:
48: """generateDownloadSet"""
49:
50: def __init__(self,folderObject,url):
51: """init downloadzip"""
52: self.folder=folderObject
53: self.done=None
54: self.response=""
55: self.url=url
56:
57: def __call__(self):
58: """call generate download zip"""
59: storeTempDir=tempfile.tempdir
1.6 casties 60: tempfile.tempdir=tdir
1.1 dwinter 61:
62: tmpPath=tempfile.mktemp()
1.6 casties 63: tmpZip=tempfile.mktemp()+".tgz"
1.1 dwinter 64: tmpFn=os.path.split(tmpZip)[1]
65:
66: if not os.path.exists(tempfile.tempdir):
67: os.mkdir(tempfile.tempdir)
68:
69: if not os.path.exists(tmpPath):
1.6 casties 70: os.mkdir(tmpPath)
1.1 dwinter 71:
1.6 casties 72: self.response="<h3>1. step: getting the files</h3>"
1.1 dwinter 73:
74: for files in self.folder.ZopeFind(self.folder,obj_metatypes=['extVersionedFile']):
1.7 ! casties 75: lastV=files[1].getContentObject()
1.1 dwinter 76: self.response+=str("<p>Get File: %s<br>\n"%lastV.title)
77:
78: savePath=os.path.join(tmpPath,lastV.title)
79: fh=file(savePath,"w")
1.2 dwinter 80: fh.write(lastV.getData())
1.1 dwinter 81: fh.close()
82:
83: self.response+="<h3>2. step: creating the downloadable file</h3>"
1.6 casties 84: self.response+="<p>Create gtar<br>"
1.1 dwinter 85: self.response+="<p>This can take a while....<br>\n"
86:
87: fh=os.popen2("tar zcvf %s %s/*"%(tmpZip,tmpPath),1)[1]
88: self.response+="<br>"
89: for c in fh.read():
90: self.response+=c
91: if c==")":
92: self.response+="<br>\n"
93:
94: shutil.rmtree(tmpPath)
95:
96: self.response+="<p>finished<br>\n"
97:
98: len=os.stat(tmpZip)[6]
99: downloadUrl=self.url+"/downloadSet"
100: self.response+="""<h1><a href="downloadSet?fn=%s">Click here for download ( %i Byte)</a></h1>\n"""%(tmpFn,len)
101: self.response+="""<p>The file you receive is a tar (gnutar) compressed file, after unpacking you will find a new folder <emph>tmp</emph> where the files are stored in.</p>"""
102: self.response+="""<p>The file will be stored for a while, you can download it later, the URL is:</p>
103: <p><a href="downloadSet?fn=%s">%s?fn=%s</a></h1>\n"""%(tmpFn,downloadUrl,tmpFn)
104:
105: self.done=True
106:
1.6 casties 107:
1.1 dwinter 108: def getResult(self):
109: """get result"""
110: return self.response
111:
112: def isDone(self):
113: if self.done:
114: return True
115: else:
116: return False
117:
118:
119: class extVersionedFileFolder(Folder,ECHO_basis):
120: """Folder with versioned files"""
121: meta_type = "extVersionedFileFolder"
122:
123: security= ClassSecurityInfo()
124: security.declareProtected('AUTHENTICATED_USER','addFileForm')
1.6 casties 125:
1.7 ! casties 126: file_meta_type=['extVersionedFile']
1.6 casties 127:
1.1 dwinter 128: if ECHO_basis:
129: optTMP= Folder.manage_options+ECHO_basis.manage_options
130: else:
131: optTMP= Folder.manage_options
132:
133: manage_options =optTMP+(
1.6 casties 134: {'label':'Generate Index.html','action':'generateIndexHTML'},
135: {'label':'Generate Image Index.html','action':'generateIndexHTML_image'},
136: {'label':'Generate history_template.html','action':'generateHistoryHTML'},
137: {'label':'Import Folder','action':'importFolderForm'},
138: {'label':'Export Folder','action':'exportFolder'},
139: {'label':'Position of version number','action':'changeHistoryFileNamesForm'},
140: )
1.1 dwinter 141:
1.6 casties 142:
1.1 dwinter 143: def changeHistoryFileNamesForm(self):
144: """change position of version num"""
145: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeHistoryFileNamesForm.zpt')).__of__(self)
146: return pt()
147:
148:
149: def changeHistoryFileNames(self,positionVersionNum="front",RESPONSE=None):
150: """change position of version num"""
151: versions=self.ZopeFind(self,obj_metatypes=['extVersionedFileObject'],search_sub=1)
152:
153: if not (getattr(self,'positionVersionNum','front')==positionVersionNum):
154:
155: for version in versions:
1.6 casties 156:
1.1 dwinter 157: if positionVersionNum=="front":
1.6 casties 158:
1.1 dwinter 159: titleTmp=os.path.splitext(version[1].title)
160: titleTmp2="_".join(titleTmp[0].split("_")[0:-1])
161: if len(titleTmp)>1:
162: id=titleTmp[0].split("_")[-1]+"_"+titleTmp2+"."+titleTmp[1]
163: else:
164: id=titleTmp[0].split("_")[-1]+"_"+titleTmp2
165:
166: else:
167: titleTmp="_".join(version[1].getId().split("_")[1:])
168: tmp=os.path.splitext(titleTmp)
169: if len(tmp)>1:
170: id=tmp[0]+"_"+version[1].getId().split("_")[0]+tmp[1]
171: else:
172: id=tmp[0]+"_"+version[1].getId().split("_")[0]
173:
174: version[1].aq_parent.manage_renameObjects(ids=[version[1].getId()],new_ids=[id])
175: version[1].title=id
176:
177: self.positionVersionNum=positionVersionNum
178: if RESPONSE:
179: RESPONSE.redirect("manage_main")
180:
181:
182:
183: def importFolderForm(self):
184: """form fuer folder import"""
185: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','importFolderForm.zpt')).__of__(self)
186: return pt()
1.6 casties 187:
1.1 dwinter 188: def importFolder(self,path,comment="",author=None,lockedBy=None,RESPONSE=None):
189: """importiere inhalt eines folders"""
190:
191: for fileName in os.listdir(path):
192: if os.path.isfile(os.path.join(path,fileName)):
193: manage_addextVersionedFile(self,fileName,'','')
194: id=fileName
195: ob=self._getOb(fileName)
196: ob.title=id
197: file2=file(os.path.join(path,fileName))
198:
199: obj=ob.manage_addextVersionedFileObject(id,comment,author,file2,content_type='')
200:
201: if RESPONSE:
202: RESPONSE.redirect(self.REQUEST['URL1'])
203:
204: zipThreads={}
205: zipThreads2={}
206:
207: def refreshTxt(self):
208: """txt fuer refresh"""
209: tn=self.REQUEST.SESSION['threadName']
210: return """ 2;url=%s?repeat=%s """%(self.absolute_url()+"/exportFolder",tn)
211:
212: def exportFolder(self,repeat=None):
213: """exportiert alle akutellen files des folders"""
214: threadName=repeat
215:
216: downloadZip=generateDownloadZip(self,self.absolute_url())
217: downloadZip()
218: return downloadZip.getResult()
219: ## if not threadName or threadName=="":
220: ## threadStart=generateDownloadZip(self,self.absolute_url())
221: ## thread=Thread(target=threadStart)
1.6 casties 222:
1.1 dwinter 223: ## thread.start()
224:
1.6 casties 225:
1.1 dwinter 226: ## self.zipThreads[thread.getName()[0:]]=threadStart
227: ## self.zipThreads2[thread.getName()[0:]]=thread
228: ## self.REQUEST.SESSION['threadName']=thread.getName()[0:]
229: ## wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['zip_wait_template'])
230: ## if wait_template:
231: ## return wait_template[0][1]()
232: ## pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','zip_wait.zpt')).__of__(self)
233: ## return pt()
1.6 casties 234:
1.1 dwinter 235: ## else:
236: ## self.REQUEST.SESSION['threadName']=threadName
237:
238: ## if (self.zipThreads[threadName].getResult()==None):
239:
240: ## wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
241: ## if wait_template:
242: ## return wait_template[0][1]()
243:
244: ## pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','zip_wait.zpt')).__of__(self)
245: ## return pt()
246: ## else:
247: ## if self.zipThreads[threadName].isDone():
248: ## self.REQUEST.SESSION['result']=self.zipThreads[threadName].getResult()
249: ## self.zipThreads2[threadName].join()
250: ## del(self.zipThreads2[threadName])
251: ## del(self.zipThreads[threadName])
252: ## pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','zip_result.zpt')).__of__(self)
253: ## return pt()
254:
255: ## else:
256: ## self.REQUEST.SESSION['result']=self.zipThreads[threadName].getResult()
257: ## self.REQUEST.SESSION['threadName']=threadName
258: ## pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','zip_wait_result.zpt')).__of__(self)
259: ## return pt()
260:
261: def downloadSet(self,fn):
1.6 casties 262: """download prepared set"""
263: filename=os.path.join(tdir,fn)
1.1 dwinter 264:
1.6 casties 265:
266: self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename="%s" """%"downloadFileFolder.tgz")
267: self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
268: len=os.stat(filename)[6]
269: self.REQUEST.RESPONSE.setHeader("Content-Length",len)
270: images=file(filename).read()
271: self.REQUEST.RESPONSE.write(images)
272: self.REQUEST.RESPONSE.close()
1.1 dwinter 273:
274:
275:
276: def helpDownload(self):
277: """download help"""
278:
279: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','helpDownload')).__of__(self)
280: return pt()
281:
282: def generateIndexHTML_image(self,RESPONSE=None):
283: """lege standard index.html an"""
284:
285:
286: if not self.ZopeFind(self,obj_ids=['index.html']):
287: zt=ZopePageTemplate('index.html')
288: self._setObject('index.html',zt)
289: default_content_fn = os.path.join(package_home(globals()),
1.6 casties 290: 'zpt/versionFileFolderMain_image.zpt')
1.1 dwinter 291: text = open(default_content_fn).read()
292: zt.pt_edit(text, 'text/html')
293:
294: else:
295: return "already exists!"
296:
297: if RESPONSE is not None:
298: RESPONSE.redirect('manage_main')
299:
300:
301: def generateAddFileForm(self,RESPONSE=None):
302: """lege standard addfileform an"""
303: #TODO: write generateaddfileform only a dummy at them moment
304:
305: if not self.ZopeFind(self,obj_ids=['addFileForm.dtml']):
306: zt=ZopePageTemplate('index.html')
307: self._setObject('index.html',zt)
308: default_content_fn = os.path.join(package_home(globals()),
1.6 casties 309: 'zpt/versionFileFolderMain.zpt')
1.1 dwinter 310: text = open(default_content_fn).read()
311: zt.pt_edit(text, 'text/html')
312:
313: else:
314: return "already exists!"
315:
316: if RESPONSE is not None:
317: RESPONSE.redirect('manage_main')
318:
319:
320: def generateIndexHTML(self,RESPONSE=None):
321: """lege standard index.html an"""
322: if not self.ZopeFind(self,obj_ids=['index.html']):
323: zt=ZopePageTemplate('index.html')
324: self._setObject('index.html',zt)
325: default_content_fn = os.path.join(package_home(globals()),
1.6 casties 326: 'zpt/versionFileFolderMain.zpt')
1.1 dwinter 327: text = open(default_content_fn).read()
328: zt.pt_edit(text, 'text/html')
329:
330: else:
331: return "already exists!"
332:
333: if RESPONSE is not None:
334: RESPONSE.redirect('manage_main')
335:
336:
337: def generateHistoryHTML(self,RESPONSE=None):
338: """lege standard index.html an"""
339: if not self.ZopeFind(self,obj_ids=['history_template.html']):
340: zt=ZopePageTemplate('history_template.html')
341: self._setObject('history_template.html',zt)
342: default_content_fn = os.path.join(package_home(globals()),
1.6 casties 343: 'zpt/versionHistory.zpt')
1.1 dwinter 344: text = open(default_content_fn).read()
345: zt.pt_edit(text, 'text/html')
346:
347: else:
348: return "already exists!"
349:
350: if RESPONSE is not None:
351: RESPONSE.redirect('manage_main')
1.6 casties 352:
1.1 dwinter 353:
354: def getVersionedFiles(self,sortField='title'):
355: """get all versioned files"""
356:
357: def sortName(x,y):
358: return cmp(x[1].title.lower(),y[1].title.lower())
359:
360: def sortDate(x,y):
1.7 ! casties 361: return cmp(y[1].getContentObject().getTime(),x[1].getContentObject().getTime())
1.1 dwinter 362:
363: def sortComment(x,y):
1.6 casties 364: try:
365: xc=getattr(x[1],'comment','ZZZZZZZZZZZZZ').lower()
366: except:
367: xc='ZZZZZZZZZZZZZ'.lower()
368:
369: try:
370: yc=getattr(y[1],'comment','ZZZZZZZZZZZZZ').lower()
371: except:
372: yc='ZZZZZZZZZZZZZ'.lower()
373:
374: if (xc=='') or (xc=='ZZZZZZZZZZZZZ'.lower()):
375: try:
1.7 ! casties 376: xc=x[1].getContentObject().getVComment().lower()
1.6 casties 377: except:
378: xc='ZZZZZZZZZZZZZ'.lower()
379:
380: if (yc=='') or (yc=='ZZZZZZZZZZZZZ'.lower()):
381: try:
1.7 ! casties 382: yc=y[1].getContentObject().getVComment().lower()
1.6 casties 383: except:
384: yc='ZZZZZZZZZZZZZ'.lower()
385:
386: return cmp(xc,yc)
1.1 dwinter 387:
388: def sortAuthor(x,y):
389:
1.7 ! casties 390: return cmp(x[1].getContentObject().lastEditor().lower(),y[1].getContentObject().lastEditor().lower())
1.1 dwinter 391:
1.7 ! casties 392: versionedFiles=self.objectItems(self.file_meta_type)
! 393: logging.debug("versionedfiles: %s of type %s"%(repr(versionedFiles),repr(self.file_meta_type)))
1.1 dwinter 394:
395: if sortField=='title':
396: versionedFiles.sort(sortName)
397: elif sortField=='date':
398: versionedFiles.sort(sortDate)
399: elif sortField=='author':
400: versionedFiles.sort(sortAuthor)
401: elif sortField=='comment':
402: versionedFiles.sort(sortComment)
403:
404: return versionedFiles
405:
406:
407: def header_html(self):
1.5 casties 408: """zusaetzlicher header"""
1.1 dwinter 409: ext=self.ZopeFind(self,obj_ids=["header.html"])
410: if ext:
411: return ext[0][1]()
412: else:
413: return ""
414:
415:
416: security.declareProtected('View','index_html')
417: def index_html(self):
418: """main"""
419: ext=self.ZopeFind(self,obj_ids=["index.html"])
420: if ext:
421: return ext[0][1]()
422:
423: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','versionFileFolderMain')).__of__(self)
424: return pt()
425:
426:
427:
428: def addFileForm(self):
429: """add a file"""
430: ext=self.ZopeFind(self,obj_ids=["addFileForm.dtml"])
431: if ext:
432: return ext[0][1]('',globals(),version='1',AUTHENTICATED_USER=self.REQUEST.AUTHENTICATED_USER)
433:
434: out=DTMLFile('dtml/newFileAdd', globals(),Kind='versionedFileObject',kind='versionedFileObject',version='1').__of__(self)
435: return out()
436:
437:
438: def addFile(self,vC,file,author,newName='',content_type='',RESPONSE=None):
439: """ add a new file"""
440: if newName=='':
441: filename=file.filename
442: id=filename[max(filename.rfind('/'),
1.6 casties 443: filename.rfind('\\'),
444: filename.rfind(':'),
445: )+1:]
1.1 dwinter 446:
447: else:
448: id=newName
449:
450: vC=self.REQUEST.form['vC']
451: manage_addextVersionedFile(self,id,'','')
452: #if (getattr(self,'commentNonEmpty',0)==1) and vC.strip()=="":
1.6 casties 453:
1.1 dwinter 454: ob=self._getOb(id)
455: ob.title=id
456: file2=file
457:
1.5 casties 458: logging.info("ADD: %s"%repr(ob))
459: obj=ob.manage_addVersionedFileObject(id,vC,author,file2,content_type=content_type)
1.1 dwinter 460: self.REQUEST.SESSION['objID']=ob.getId()
461: self.REQUEST.SESSION['objID_parent']=None
462:
463: if obj.getSize()==0:
464: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','errorUploadFile')).__of__(self)
465: return pt()
466:
467: RESPONSE.redirect(self.REQUEST['URL1'])
468:
469:
470: def deleteEmptyObject(self,submit,RESPONSE=None):
471: """deleteemptyobject"""
472: if submit=="delete it":
473: if self.REQUEST.SESSION['objID_parent']:
474: obj=getattr(self,self.REQUEST.SESSION['objID_parent'])
475:
476: else:
477: obj=self
478: obj.manage_delObjects([self.REQUEST.SESSION['objID']])
479:
480: RESPONSE.redirect(self.REQUEST['URL1'])
481:
1.7 ! casties 482:
! 483: security.declareProtected('AUTHENTICATED_USER','fixVersionNumbers')
! 484: def fixVersionNumbers(self):
! 485: """fix last version number of all files"""
! 486: for (id,vf) in self.getVersionedFiles():
! 487: vf.fixVersionNumbers()
1.1 dwinter 488:
489: manage_addextVersionedFileFolderForm=DTMLFile('dtml/extfolderAdd', globals())
490:
491:
492: def manage_addextVersionedFileFolder(self, id, title='',
1.6 casties 493: createPublic=0,
494: createUserF=0,
495: REQUEST=None):
1.1 dwinter 496: """Add a new Folder object with id *id*.
497:
498: If the 'createPublic' and 'createUserF' parameters are set to any true
499: value, an 'index_html' and a 'UserFolder' objects are created respectively
500: in the new folder.
501: """
502: ob=extVersionedFileFolder()
503: ob.id=str(id)
504: ob.title=title
505: self._setObject(id, ob)
506: ob=self._getOb(id)
507:
508: checkPermission=getSecurityManager().checkPermission
509:
510: if createUserF:
511: if not checkPermission('Add User Folders', ob):
512: raise Unauthorized, (
1.6 casties 513: 'You are not authorized to add User Folders.'
514: )
1.1 dwinter 515: ob.manage_addUserFolder()
516:
1.6 casties 517:
1.1 dwinter 518: if REQUEST is not None:
519: return self.manage_main(self, REQUEST, update_menu=1)
520:
521:
522:
523: class extVersionedFileObject(ExtFile):
524: """File Object im Folder"""
525: security= ClassSecurityInfo()
526: meta_type = "extVersionedFileObject"
527:
1.7 ! casties 528: manage_editForm=DTMLFile('dtml/fileEdit',globals(),
1.1 dwinter 529: Kind='File',kind='file')
530: manage_editForm._setName('manage_editForm')
531:
1.7 ! casties 532: def __init__(self, id, title='', versionNumber=0, versionComment=None, time=None, author=None):
! 533: """Initialize a new instance of extVersionedFileObject (taken from ExtFile)"""
! 534: ExtFile.__init__(self,id,title)
! 535: self.versionNumber = versionNumber
! 536: self.versionComment= versionComment
! 537: self.time = time
! 538: self.author = author
! 539:
! 540:
1.1 dwinter 541: security.declarePublic('getTitle')
542: def getTitle(self):
543: """get title"""
544: return self.title
1.6 casties 545:
546: def getData(self):
547: """returns object content (calls ExtFile.index_html)"""
548: return ExtFile.index_html(self)
549:
1.1 dwinter 550: security.declarePublic('getVComment')
551: def getVComment(self):
552: """get the comment of this file"""
553: if not hasattr(self,'vComment') or (not self.vComment) or (self.vComment.lstrip()==""):
554: return "Add comment"
555:
556: else:
557: return self.vComment
1.6 casties 558:
1.1 dwinter 559: def manageVCommentForm(self):
560: """add a comment"""
561: self.REQUEST.SESSION['refer']=self.REQUEST['HTTP_REFERER']
562: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addVComment')).__of__(self)
563: return pt()
564:
565: def manageVComment(self,text,comment_author,submit,REQUEST=None):
566: """manage comments"""
567: if submit =='change':
568: if text=='':
569: self.vComment=None
570: else:
571: self.vComment=text
572: self.vComment_author=comment_author
573:
574: self.vComment_date=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
575:
576: if self.REQUEST.SESSION.has_key('refer'):
577:
578: return REQUEST.RESPONSE.redirect(self.REQUEST.SESSION['refer'])
579: return REQUEST.RESPONSE.redirect(self.aq_parent.absolute_url()+"/history")
580:
581:
582: security.declarePublic('getVersionComment')
583: def getVersionComment(self):
584: """getversioncomment"""
585: return self.versionComment
586:
587: security.declarePublic('getTime')
588: def getTime(self):
589: """getTime"""
590: #return self.bobobase_modification_time().ISO()
591: if hasattr(self,'time'):
592: return time.strftime("%Y-%m-%d %H:%M:%S",self.time)
593: elif hasattr(self,'timefixed'):
1.6 casties 594: return self.timefixed
1.1 dwinter 595: else:
596: setattr(self,'timefixed',self.bobobase_modification_time().ISO())
597: return self.bobobase_modification_time().ISO()
598:
599: def download(self,REQUEST=None,RESPONSE=None):
600: """download and lock"""
601:
602: self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename=%s"""%self.getId())
603: self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
604: #try:
605: # txt=self.index_html()
606: #except:
607: # txt=self.index_html(REQUEST,RESPONSE)
608: #
609: #self.REQUEST.RESPONSE.setHeader("Content-Length","str(len(txt)+1000)")
610:
611: self.content_type="application/octet-stream"
612: self.REQUEST.RESPONSE.redirect(self.absolute_url())
613: #txt=urllib.urlopen(self.absolute_url()).read()
614: #self.REQUEST.RESPONSE.write(txt)
615:
616:
617: #self.REQUEST.close()
618:
619: security.declareProtected('AUTHENTICATED_USER','downloadLocked')
620: def downloadLocked(self):
621: """download and lock"""
622:
623:
624: if repr(self.REQUEST['AUTHENTICATED_USER'])=='Anonymous User':
625: return "please login first"
626: if not self.aq_parent.lockedBy=="":
627: return "cannot be locked because is already locked by %s"%self.lockedBy
628: self.aq_parent.lockedBy=self.REQUEST['AUTHENTICATED_USER']
629:
630: self.content_type="application/octet-stream"
631: self.REQUEST.RESPONSE.redirect(self.absolute_url())
632:
633: security.declarePublic('getVersionNumber')
634: def getVersionNumber(self):
635: """get version"""
636: return self.versionNumber
637:
638: security.declarePublic('getVersionComment')
639: def getVersionComment(self):
640: """get version"""
641: return self.versionComment
642:
643: security.declarePublic('lastEditor')
644: def lastEditor(self):
645: """last Editor"""
646: if hasattr(self,'author'):
647: try:
648: ret=self.author.replace("-","\n")
649: except:#old version of versionded file sometimes stored the user object and not only the name the following corrects this
650: ret=str(self.author).replace("-","\n")
651: ret=ret.replace("\r","\n")
652: return ret.lstrip().rstrip()
653:
654: else:
655: jar=self._p_jar
656: oid=self._p_oid
657:
658: if jar is None or oid is None: return None
659:
660: return jar.db().history(oid)[0]['user_name']
661:
662:
663: manage_addextVersionedFileObjectForm=DTMLFile('dtml/fileAdd', globals(),Kind='extVersionedFileObject',kind='extVersionedFileObject', version='1')
664:
1.7 ! casties 665: def manage_addextVersionedFileObject(self,id,vC='',author='', file='',title='',versionNumber=0,
! 666: precondition='', content_type='', REQUEST=None):
1.1 dwinter 667: """Add a new File object.
668:
669: Creates a new File object 'id' with the contents of 'file'"""
670:
671: id=str(id)
672: title=str(title)
673: content_type=str(content_type)
674: precondition=str(precondition)
675:
676: id, title = cookId(id, title, file)
677:
678: self=self.this()
679:
680: # First, we create the file without data:
1.7 ! casties 681: self._setObject(id, extVersionedFileObject(id,title,versionNumber=versionNumber,versionComment=str(vC),author=author))
! 682: fob = self._getOb(id)
1.1 dwinter 683:
684: # Now we "upload" the data. By doing this in two steps, we
685: # can use a database trick to make the upload more efficient.
686: if file:
1.7 ! casties 687: fob.manage_upload(file)
1.1 dwinter 688: if content_type:
1.7 ! casties 689: fob.content_type=content_type
1.1 dwinter 690:
691: if REQUEST is not None:
692: REQUEST['RESPONSE'].redirect(self.absolute_url()+'/manage_main')
693:
694:
695:
696: class extVersionedFile(CatalogAware,Folder):
697: """Versioniertes File"""
698:
1.7 ! casties 699: meta_type = 'extVersionedFile'
! 700: # meta_type of contained objects
! 701: content_meta_type = ['extVersionedFileObject']
! 702: default_catalog = 'fileCatalog'
1.1 dwinter 703:
1.7 ! casties 704: security=ClassSecurityInfo()
1.1 dwinter 705:
1.7 ! casties 706: def __init__(self, id, title, lockedBy,author):
! 707: """init"""
! 708: self.id=id
! 709: self.title=title
! 710: self.lockedBy=lockedBy
! 711: self.author=author
! 712: self.lastVersionNumber=0
! 713: self.lastVersionId=None
! 714:
1.1 dwinter 715: security.declarePublic('getTitle')
716: def getTitle(self):
717: """get title"""
718: return self.title
719:
720: def PrincipiaSearchSource(self):
1.6 casties 721: """Return cataloguable key for ourselves."""
722: return str(self)
1.1 dwinter 723:
724: def manageImagesForm(self):
725: """manage Images attached to the file"""
726:
727: self.REQUEST.SESSION['refer']=self.REQUEST['HTTP_REFERER']
728:
729: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','manageImage')).__of__(self)
730: return pt()
731:
732: def manageImages(self,imageUrl=None,caption=None,REQUEST=None):
733: """manage URL"""
734: if imageUrl and (not imageUrl==""):
735: manage_AddImageZogiLib(self,libPath=imageUrl,caption=caption)
736:
737: if self.REQUEST.SESSION.has_key('refer'):
738:
739: return REQUEST.RESPONSE.redirect(self.REQUEST.SESSION['refer'])
740: return REQUEST.RESPONSE.redirect(self.aq_parent.absolute_url())
741:
742: def changeImages(self,caption=None,submit=None,id=None,REQUEST=None):
743: """manage URL"""
744: if submit=="change caption":
745: image=self.ZopeFind(self,obj_ids=[id])
746: if image:
747: image[0][1].caption=caption[0:]
748:
749: elif submit=="delete":
750: image=self.ZopeFind(self,obj_ids=[id])
751: if image:
752: self.manage_delObjects([image[0][1].getId()])
753:
754: if self.REQUEST.SESSION.has_key('refer'):
1.7 ! casties 755: return REQUEST.RESPONSE.redirect(self.REQUEST.SESSION['refer'])
1.1 dwinter 756:
757: return REQUEST.RESPONSE.redirect(self.aq_parent.absolute_url())
758:
759: def getImages(self):
760: """get Images"""
761: images=self.ZopeFind(self,obj_metatypes=["ImageZogiLib"])
762: if not images:
763: return None
764: else:
765: return images
1.6 casties 766:
1.1 dwinter 767: security.declarePublic('getComment')
768: def getComment(self):
769: """get the comment of this file"""
770: if not hasattr(self,'comment') or (not self.comment) or (self.comment.lstrip()==""):
771: return "Add comment"
772: else:
773: return self.comment
774:
775: def manageCommentForm(self):
776: """add a comment"""
777: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addComment')).__of__(self)
778: return pt()
779:
780: def manageComment(self,text,comment_author,submit,REQUEST=None):
781: """manage comments"""
782: if submit =='change':
783: if text=='':
784: self.comment=None
785: else:
786: self.comment=text
787: self.comment_author=comment_author
788:
789: self.comment_date=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
790:
791: return REQUEST.RESPONSE.redirect(self.aq_parent.absolute_url())
1.6 casties 792:
1.1 dwinter 793: security.declarePublic('getLastChangeDate')
794: def getLastChangeDate(self):
795: """get last change date"""
1.7 ! casties 796: lv=self.getContentObject()
1.1 dwinter 797: time=lv.getTime()
798: return time
799:
800: def getLastEditor(self):
801: """get last change date"""
1.7 ! casties 802: lv=self.getContentObject()
1.1 dwinter 803: le=lv.lastEditor()
804: return le
805:
806: def getLockedBy(self):
807: """get locked by"""
808: return str(self.lockedBy)
1.6 casties 809:
1.7 ! casties 810: def getLastVersionNumber(self):
! 811: """returns the highest version number of all included objects"""
! 812: lv = self.findLastVersion()
! 813: if lv:
! 814: return lv.getVersionNumber()
! 815: else:
! 816: return 0
! 817:
! 818: def findLastVersion(self):
! 819: """finds and returns the object with the highest version number"""
! 820: lvn=0
! 821: lv=None
! 822:
! 823: for v in self.objectValues(self.content_meta_type):
! 824: logging.debug("findlastversion: check %s"%v.getId())
! 825: if v.getVersionNumber() > lvn:
! 826: lvn=v.getVersionNumber()
! 827: lv=v
! 828:
! 829: if lv:
! 830: logging.debug("findlastversion: got %s"%lv.getId())
! 831: return lv
! 832:
1.1 dwinter 833: security.declarePublic('getLastVersion')
834: def getLastVersion(self):
1.7 ! casties 835: """Last Version (old)"""
1.1 dwinter 836: tmp=0
1.7 ! casties 837: lv=None
1.1 dwinter 838:
1.7 ! casties 839: for v in self.objectValues(self.content_meta_type):
! 840: logging.debug("getlastversion: check %s"%v.getId())
! 841: if v.getVersionNumber() > tmp:
! 842: tmp=v.getVersionNumber()
! 843: lv=v
! 844:
! 845: logging.debug("getlastversion: got %s"%lv.getId())
! 846: return lv
! 847:
! 848: def getContentObject(self):
! 849: """returns the last version object"""
! 850: if not self.lastVersionId:
! 851: lv = self.findLastVersion()
! 852: if lv is None:
! 853: return None
! 854: self.lastVersionNumber = lv.getVersionNumber()
! 855: self.lastVersionId = lv.getId()
1.1 dwinter 856:
1.7 ! casties 857: return getattr(self, self.lastVersionId)
! 858:
! 859: security.declarePublic('getData')
! 860: def getData(self):
! 861: """Returns the content of the last version"""
! 862: ob = self.getContentObject()
! 863: if ob is not None:
! 864: return ob.getData()
! 865: else:
! 866: return None
1.1 dwinter 867:
868: def diff(self,data):
869: """differenz between lastversion and data"""
870: d=Differ()
1.7 ! casties 871: tmp=self.getData()
1.1 dwinter 872: #print "XX",data,tmp
873: try:
1.6 casties 874: l=list(d.compare(data.splitlines(1),tmp.splitlines(1)))
1.1 dwinter 875: except:
876: return 0,""
877: plus=0
878: minus=0
879: for a in l:
880: if a[0]=='+':
881: plus+=1
882: if a[0]=='-':
883: minus+=1
884:
885: return max([plus,minus]),l
1.6 casties 886:
887:
1.1 dwinter 888: security.declarePublic('index_html')
889: def index_html(self):
890: """main view"""
1.7 ! casties 891: #lastVersion=self.getContentObject()
1.1 dwinter 892: #return "File:"+self.title+" Version:%i"%lastVersion.versionNumber," modified:",lastVersion.bobobase_modification_time()," size:",lastVersion.getSize(),"modified by:",lastVersion.lastEditor()
1.4 dwinter 893: #return "File: %s Version:%i modified:%s size:%s modified by:%s"%(self.title,lastVersion.versionNumber,lastVersion.getTime(),lastVersion.getSize(),lastVersion.lastEditor())
894: return self.history()
1.1 dwinter 895:
1.6 casties 896:
1.1 dwinter 897: security.declarePublic('getVersion')
898: def getVersion(self):
1.7 ! casties 899: # TODO: this is ugly and it returns the next version number
1.1 dwinter 900: tmp=0
901: for version in self.ZopeFind(self):
902:
903: if hasattr(version[1],'versionNumber'):
904:
905: if int(version[1].versionNumber) > tmp:
906: tmp=int(version[1].versionNumber,)
1.7 ! casties 907: return tmp+1
1.1 dwinter 908:
909: def history(self):
910: """history"""
911: ext=self.ZopeFind(self.aq_parent,obj_ids=["history_template.html"])
912: if ext:
913: return getattr(self,ext[0][1].getId())()
914:
915: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','versionHistory')).__of__(self)
916: return pt()
917:
918: def getVersions(self):
919: """get all versions"""
920: ret=[]
921: for version in self.ZopeFind(self):
922: if hasattr(version[1],'versionNumber'):
923: ret.append((version[1].versionNumber,version[1]))
924: ret.sort(sortv)
925: return ret
926:
927: security.declareProtected('AUTHENTICATED_USER','forceunlock')
928: def forceunlock(self,RESPONSE=None):
929: """unlock"""
930: #safe who had the lock
931: if self.lockedBy:
932: self.brokenLock=str(self.lockedBy)
933: else:
934: self.brokenLock=""
935: self.lockedBy=''
936: return self.brokenLock
937:
938: security.declareProtected('AUTHENTICATED_USER','unlock')
939: def unlock(self,RESPONSE):
940: """unlock"""
941: if str(self.lockedBy) in [str(self.REQUEST['AUTHENTICATED_USER'])]:
942: self.lockedBy=''
943: RESPONSE.redirect(self.REQUEST['HTTP_REFERER'])
944: else:
945: return "Sorry, not locked by you! (%s,%s)"%(self.lockedBy,self.REQUEST['AUTHENTICATED_USER'])
946:
1.7 ! casties 947:
! 948: def _newContentObject(self, id, title='', versionNumber=0, versionComment=None, time=None, author=None):
! 949: """factory for content objects. to be overridden in derived classes."""
! 950: return extVersionedFileObject(id,title,versionNumber=versionNumber,versionComment=versionComment,time=time,author=author)
! 951:
! 952:
! 953: def addContentObject(self,id,vC,author=None,file=None,title='',changeName='no',newName='',from_tmp=False,
! 954: precondition='', content_type=''):
! 955: """add"""
! 956:
! 957: if changeName=="yes":
! 958: filename=file.filename
! 959: self.title=filename[max(filename.rfind('/'),
! 960: filename.rfind('\\'),
! 961: filename.rfind(':'),
! 962: )+1:]
! 963:
! 964: if not newName=='':
! 965: self.title=newName[0:]
! 966:
! 967: posVersNum=getattr(self,'positionVersionNum','front')
! 968:
! 969: versNum = self.getLastVersionNumber() + 1
! 970:
! 971: if posVersNum=='front':
! 972: id="V%i_%s"%(versNum,self.title)
! 973: else:
! 974: fn=os.path.splitext(self.title)
! 975: if len(fn)>1:
! 976: id=fn[0]+"_V%i%s"%(versNum,fn[1])
! 977: else:
! 978: id=fn[0]+"_V%i"%versNum
1.1 dwinter 979:
1.7 ! casties 980: # what does this do?
! 981: id, title = cookId(id, title, file)
! 982: self=self.this()
! 983:
! 984: # First, we create the file without data:
! 985: self._setObject(id, self._newContentObject(id,title,versionNumber=versNum,versionComment=str(vC),
! 986: time=time.localtime(),author=author))
! 987: fob = self._getOb(id)
! 988:
! 989: # Now we "upload" the data. By doing this in two steps, we
! 990: # can use a database trick to make the upload more efficient.
! 991: if file and not from_tmp:
! 992: fob.manage_upload(file)
! 993: elif file and from_tmp:
! 994: fob.manage_file_upload(file) # manage_upload_from_tmp doesn't exist in ExtFile2
! 995: # fob.manage_upload_from_tmp(file) # manage_upload_from_tmp doesn't exist in ExtFile2
! 996: fob.content_type=content_type
! 997:
! 998: self.lastVersionNumber = versNum
! 999: self.lastVersionId = id
! 1000:
! 1001: logging.debug("addcontentobject: lastversion=%s"%self.getData())
! 1002: logging.debug("reindex1: %s in %s"%(repr(self),repr(self.default_catalog)))
! 1003: self.reindex_object()
! 1004: logging.debug("addcontentobject: fob_data=%s"%fob.getData())
! 1005:
! 1006: return fob
! 1007:
1.1 dwinter 1008:
1009: security.declareProtected('AUTHENTICATED_USER','addVersionedFileObjectForm')
1010: def addVersionedFileObjectForm(self):
1011: """add a new version"""
1012:
1013: if str(self.REQUEST['AUTHENTICATED_USER']) in ["Anonymous User"]:
1014: return "please login first"
1015: if (self.lockedBy==self.REQUEST['AUTHENTICATED_USER']) or (self.lockedBy==''):
1016: ext=self.ZopeFind(self.aq_parent,obj_ids=["addNewVersion.dtml"])
1017: if ext:
1.7 ! casties 1018: return ext[0][1]('',globals(),version=self.getVersion(),lastComment=self.getContentObject().getVersionComment(),AUTHENTICATED_USER=self.REQUEST.AUTHENTICATED_USER)
1.1 dwinter 1019: else:
1020: out=DTMLFile('dtml/fileAdd', globals(),Kind='VersionedFileObject',kind='versionedFileObject',version=self.getVersion()).__of__(self)
1021: return out()
1022: else:
1023: return "Sorry file is locked by somebody else"
1.7 ! casties 1024:
1.1 dwinter 1025:
1.7 ! casties 1026: def manage_addVersionedFileObject(self,id,vC,author,file='',title='',precondition='', content_type='',changeName='no',newName='', from_tmp=False, RESPONSE=None):
1.1 dwinter 1027: """add"""
1028: try: #der ganze vC unsinn muss ueberarbeitet werden
1029: vC=self.REQUEST['vC']
1030: except:
1031: pass
1032:
1033: author=self.REQUEST['author']
1034:
1.7 ! casties 1035: ob = self.addContentObject(id, vC, author, file, title, changeName=changeName, newName=newName, from_tmp=from_tmp,
! 1036: precondition=precondition, content_type=content_type)
! 1037:
1.1 dwinter 1038: self.REQUEST.SESSION['objID_parent']=self.getId()
1039:
1040: if RESPONSE:
1.7 ! casties 1041: if ob.getSize()==0:
! 1042: self.REQUEST.SESSION['objID']=ob.getId()
1.1 dwinter 1043: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','errorUploadFile')).__of__(self)
1044: return pt()
1045:
1046: else:
1047: RESPONSE.redirect(self.REQUEST['URL2'])
1048: else:
1.7 ! casties 1049: return ob
1.6 casties 1050:
1.1 dwinter 1051:
1052: def download(self):
1053: """download and lock"""
1.7 ! casties 1054: self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename=%s"""%self.getContentObject().getId())
1.1 dwinter 1055: self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
1056: self.content_type="application/octet-stream"
1.7 ! casties 1057: self.REQUEST.RESPONSE.redirect(self.REQUEST['URL1']+'/'+self.getId()+'/'+self.getContentObject().getId())
1.1 dwinter 1058:
1059: security.declareProtected('AUTHENTICATED_USER','downloadLocked')
1060: def downloadLocked(self):
1061: """download and lock"""
1062:
1063: if repr(self.REQUEST['AUTHENTICATED_USER'])=='Anonymous User':
1064: return "please login first"
1065: if not self.lockedBy=="":
1066: return "cannot be locked because is already locked by %s"%self.lockedBy
1067: self.lockedBy=self.REQUEST['AUTHENTICATED_USER']
1.7 ! casties 1068: self.getContentObject().content_type="application/octet-stream"
! 1069: self.REQUEST.RESPONSE.redirect(self.REQUEST['URL1']+'/'+self.getId()+'/'+self.getContentObject().getId())
! 1070:
! 1071:
! 1072: security.declareProtected('AUTHENTICATED_USER','fixVersionNumbers')
! 1073: def fixVersionNumbers(self):
! 1074: """check last version number and id"""
! 1075: if not hasattr(self, 'lastVersionId'):
! 1076: self.lastVersionNumber = 0
! 1077: self.lastVersionId = None
! 1078:
! 1079: lv = self.getContentObject()
! 1080: if lv is not None:
! 1081: lvn = lv.getVersionNumber()
! 1082: if lvn == 0:
! 1083: lvn = 1
! 1084: lv.versionNumber = 1
! 1085: self.lastVersionNumber = lvn
! 1086: self.lastVersionId = lv.getId()
! 1087: else:
! 1088: self.lastVersionNumber = 0
! 1089: self.lastVersionId = None
! 1090: logging.debug("fixing last version number of %s to %s (%s)"%(self.getId(),self.lastVersionNumber,self.lastVersionId))
! 1091:
1.1 dwinter 1092:
1093: def manage_addextVersionedFileForm(self):
1094: """interface for adding the OSAS_root"""
1095: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addextVersionedFile.zpt')).__of__(self)
1096: return pt()
1097:
1098: def manage_addextVersionedFile(self,id,title,lockedBy, author=None, RESPONSE=None):
1099: """add the OSAS_root"""
1100: newObj=extVersionedFile(id,title,lockedBy,author)
1101: self._setObject(id,newObj)
1.6 casties 1102:
1.1 dwinter 1103: if RESPONSE is not None:
1104: RESPONSE.redirect('manage_main')
1105:
1106:
1107: InitializeClass(extVersionedFile)
1108: InitializeClass(extVersionedFileFolder)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>