File:  [Repository] / versionedFile / extVersionedFile.py
Revision 1.10: download - view: text, annotated - select for diffs - revision graph
Fri Sep 14 12:06:55 2007 UTC (16 years, 8 months ago) by casties
Branches: MAIN
CVS tags: HEAD
added import method to convert old versioned file folder to extVersionedFileFolder

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

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