File:  [Repository] / cdli / cdli_files.py
Revision 1.3: download - view: text, annotated - select for diffs - revision graph
Thu Dec 8 17:11:31 2005 UTC (18 years, 6 months ago) by dwinter
Branches: MAIN
CVS tags: HEAD
upload

    1: """CDLI extensions of the filearchive"""
    2: from Products.versionedFile.versionedFile import *
    3: from Products.ZCatalog.CatalogPathAwareness import CatalogAware
    4: from tempfile import mkstemp,mkdtemp
    5: import os.path
    6: import os
    7: from types import *
    8: import urlparse
    9: 
   10: class Basket(Folder):
   11:     """shopping basket"""
   12:     
   13:     meta_type="Basket"
   14:     _v_stack={}
   15: 
   16:     def getObjUrl(self,objId):
   17:         """getUrl"""
   18:         founds=self.CDLICatalog.search({'path':objId})
   19:         if len(founds)>0:
   20:              return founds[0].getObject().absolute_url()
   21:          
   22:         else: #assume version
   23:             splitted=objId.split("_")
   24:             founds=self.CDLICatalog.search({'path':splitted[1]})        
   25:             return founds[0].getObject().absolute_url()+'/'+objId
   26:         
   27:     def storeAllLink(self,results):
   28:         """erzeuge link zum speicher aller results"""
   29:         nr=self.REQUEST['_ZopeId']
   30:         
   31:         if results:
   32:             self._v_stack[nr]=[x.getObject().getId() for x in results]
   33:         
   34:         return self.absolute_url()+"/storeAll?id="+nr
   35:     
   36:     def storeAll(self,id):
   37:         """store all"""
   38:         try:
   39:             results=self._v_stack[id]
   40:         except:
   41:             #TODO: write expired page
   42:             return "expired"
   43:         
   44:         return self.storeInBasketForm(results)
   45:         
   46:     def storeInBasketForm(self,ids):
   47:         """ store an object form"""
   48:         
   49:         if type(ids) is not ListType:
   50:             ids=[ids]
   51:         self.REQUEST.SESSION['ids']=ids[0:]
   52:         
   53:         self.REQUEST.SESSION['BACKLINK']=self.REQUEST['HTTP_REFERER']
   54: 
   55:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','storeBasketObject.zpt')).__of__(self)
   56:         return pt()
   57:         
   58:     def storeInBasket(self,username,ids=None,RESPONSE=None,REQUEST=None):
   59:         """store it"""
   60:         
   61:         if not ids:
   62:             ids=REQUEST.SESSION['ids']
   63:             
   64:         self.REQUEST.SESSION['basketUser']=username
   65:         
   66:         baskets=self.ZopeFind(self,obj_ids=[username])
   67:         if len(baskets)>0:
   68:             basket=baskets[0][1]
   69:         else:
   70:             manage_addBasketObject(self,username)
   71:             basket=self._getOb(username)
   72:         
   73:         
   74:         basket.addObjects(ids)
   75:         back=self.REQUEST.SESSION.get('BACKLINK', None)
   76: 
   77:         if RESPONSE:
   78:             RESPONSE.redirect(back)
   79:             
   80: 
   81:     
   82:     def showBasket(self,user=None,set=None,RESPONSE=None):
   83:         """show the basket"""
   84:         
   85:         if user:
   86:             self.REQUEST.SESSION['basketUser']=user
   87:         
   88:         if not user and not set:
   89:             user=self.REQUEST.SESSION.get('basketUser',None)
   90:         
   91:         if not user:
   92:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','authorizeBasketUser.zpt')).__of__(self)
   93:             return pt()
   94:         else:
   95:             baskets=self.ZopeFind(self,obj_ids=[user])
   96:         
   97: 
   98:         if len(baskets)>0:
   99:             RESPONSE.redirect(baskets[0][1].absolute_url())
  100:             return True 
  101:         else:
  102:             pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','emptyBasket.zpt')).__of__(self)
  103:             return pt()
  104:         
  105: 
  106: def manage_addBasketForm(self):
  107:     """add the basket form"""
  108:     pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addBasket.zpt')).__of__(self)
  109:     return pt()
  110: 
  111: def manage_addBasket(self,id,title,RESPONSE=None):
  112:     """add the basket"""
  113:     ob=Basket()
  114:     
  115:     ob.id=str(id)
  116:     ob.title=title
  117:     self._setObject(id, ob)
  118:     ob=self._getOb(id)
  119:     
  120:     if RESPONSE is not None:
  121:         RESPONSE.redirect('manage_main')
  122: 
  123:     
  124: class BasketObject(Folder):
  125:     """Basket Object"""
  126:     
  127:     meta_type="basketObject"
  128:     def __init__(self):
  129:         	"""init basket object"""
  130:         	self.contents=[]
  131: 
  132:     def numberOfItems(self):
  133:         """return anzahl der elemente im basket"""
  134:         return len(self.contents)
  135:     
  136:     def addObjects(self,ids):
  137:         """addObjects"""
  138:         
  139:         for id in ids:
  140:             founds=self.CDLICatalog.search({'path':id})
  141:             for found in founds:
  142:                 if found.getObject() not in self.contents:
  143:                     tm=self.contents[0:]
  144:                     tm.append(found.getObject())
  145:                     self.contents=tm[0:]
  146:     
  147:         return True
  148: 
  149:     def index_html(self):
  150:         	"""view the basket"""
  151:         	pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','basketObject_index_html.zpt')).__of__(self)
  152:         	return pt()
  153: 
  154:     def deleteObjects(self,ids,RESPONSE=None):
  155:         """delete objects"""
  156:         list = self.contents[0:]
  157:         for content in list:
  158:                
  159:                 if content.getId() in ids:
  160:                     self.contents.remove(content)
  161:         
  162: 
  163:         if RESPONSE:
  164:         	    RESPONSE.redirect(self.absolute_url())
  165: 
  166: 
  167:     def unlockTest(self):
  168:         """unlock all files of the testuser for debuggin"""
  169:         for object in self.contents:
  170: 
  171:                 if str(object.lockedBy)=="test":
  172:                     object.lockedBy=""
  173:             
  174:     def downloadObjectsAsOneFile(self,lock=None,procedure=None,REQUEST=None):
  175:         """download all selected files in one file"""
  176:         
  177:         ret=""
  178:         lockedObjects={}
  179:         
  180: 
  181:         if lock:
  182:             
  183:             if str(self.REQUEST['AUTHENTICATED_USER'])=='Anonymous User':
  184:                 
  185:                 return "please login first"
  186: 
  187:             #check if a locked object exist in the basket.
  188:             lockedObjects={}
  189:             for object in self.contents:
  190: 
  191:                 if not object.lockedBy=="":
  192:                     lockedObjects[object.title]=repr(object.lockedBy)
  193:                    
  194:                     
  195:             keys=lockedObjects.keys()
  196:             
  197:             
  198:             if len(keys)>0 and (not procedure):
  199:                 self.REQUEST.SESSION['lockedObjects']=lockedObjects
  200:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','lockedObjects.zpt')).__of__(self)
  201:                 return pt()
  202:          
  203:             elif not procedure: #keine fails gesperrt dann alle donwloaden
  204:                 procedure="downloadAll" 
  205:         
  206:         print procedure    
  207:         for object in self.contents:
  208:             
  209:                 if (procedure=="downloadAll") or (object.lockedBy=='') or (object.lockedBy==self.REQUEST['AUTHENTICATED_USER']):
  210:                     ret+=object.getLastVersion().data
  211:                 
  212:                 if lock and object.lockedBy=='':
  213:                     object.lockedBy=self.REQUEST['AUTHENTICATED_USER']
  214: 
  215: 
  216:         self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename="basket_%s.atf" """%self.getId())
  217:         self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
  218:         length=len(ret)
  219:         self.REQUEST.RESPONSE.setHeader("Content-Length",length)
  220:         self.REQUEST.RESPONSE.write(ret)    
  221:         
  222:         
  223: def manage_addBasketObjectForm(self):
  224:     """add form"""
  225:     pass
  226: 
  227: def manage_addBasketObject(self,id,title='',RESPONSE=None):
  228:     """add"""
  229:     
  230:     ob=BasketObject()
  231:     
  232:     ob.id=str(id)
  233:     ob.title=title
  234:     self._setObject(id, ob)
  235:     ob=self._getOb(id)
  236:     
  237:     if RESPONSE is not None:
  238:         RESPONSE.redirect('manage_main')
  239: 
  240: class CDLIFileObject(versionedFileObject):
  241:     """CDLI file object"""
  242:     
  243:     meta_type="CDLI File Object"
  244:     
  245:         
  246:     def view(self):
  247:         """view file"""
  248:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','viewCDLIFile.zpt')).__of__(self)
  249:         return pt()
  250:     
  251: manage_addCDLIFileObjectForm=DTMLFile('dtml/fileAdd', globals(),Kind='CDLIFileObject',kind='CDLIFileObject', version='1')
  252: 
  253: def manage_addCDLIFileObject(self,id,vC='',author='', file='',title='',precondition='', content_type='',
  254:                    REQUEST=None):
  255:     """Add a new File object.
  256: 
  257:     Creates a new File object 'id' with the contents of 'file'"""
  258: 
  259:     id=str(id)
  260:     title=str(title)
  261:     content_type=str(content_type)
  262:     precondition=str(precondition)
  263:     
  264:     id, title = cookId(id, title, file)
  265: 
  266:     self=self.this()
  267: 
  268:     # First, we create the file without data:
  269:     self._setObject(id, CDLIFileObject(id,title,'',content_type, precondition))
  270:     self._getOb(id).versionComment=str(vC)
  271:     self._getOb(id).time=time.localtime()
  272:     
  273:     setattr(self._getOb(id),'author',author)
  274:     
  275:     # Now we "upload" the data.  By doing this in two steps, we
  276:     # can use a database trick to make the upload more efficient.
  277:     if file:
  278:         self._getOb(id).manage_upload(file)
  279:     if content_type:
  280:         self._getOb(id).content_type=content_type
  281: 
  282:     if REQUEST is not None:
  283:         REQUEST['RESPONSE'].redirect(self.absolute_url()+'/manage_main')
  284:     
  285: class CDLIFile(versionedFile,CatalogAware):
  286:     """CDLI file"""
  287:     
  288:     meta_type="CDLI file"
  289:     default_catalog='CDLICatalog'
  290: 
  291:     def manage_addCDLIFileObject(self,id,vC,author,file='',title='',precondition='', content_type='',changeName='no',newName='', RESPONSE=None):
  292:         """add"""
  293:         try: #TODO: der ganze vC unsinn muss ueberarbeitet werden
  294:             vC=self.REQUEST['vC']
  295:         except:
  296:             pass
  297:         
  298:         author=self.REQUEST['author']
  299:         
  300:         if changeName=="yes":
  301:             filename=file.filename
  302:             self.title=filename[max(filename.rfind('/'),
  303:                         filename.rfind('\\'),
  304:                         filename.rfind(':'),
  305:                         )+1:]
  306: 
  307: 
  308:         if not newName=='':
  309:             self.title=newName[0:]
  310:         
  311:         
  312: 
  313:         
  314:         
  315:         positionVersionNum=getattr(self,'positionVersionNum','front')
  316:         
  317:         if positionVersionNum=='front':
  318:             id="V%i"%self.getVersion()+"_"+self.title
  319:         else:
  320:             tmp=os.path.splitext(self.title)
  321:             if len(tmp)>1:
  322:                 id=tmp[0]+"_V%i"%self.getVersion()+tmp[1]
  323:             else:
  324:                 id=tmp[0]+"_V%i"%self.getVersion()
  325:             
  326:         
  327:         manage_addCDLIFileObject(self,id,vC,author,file,id,precondition, content_type)
  328:         objs=self.ZopeFind(self,obj_ids=[id])[0][1].setVersionNumber(int(self.getVersion()))
  329:         self.REQUEST.SESSION['objID_parent']=self.getId()
  330: 
  331:         if RESPONSE:
  332:             obj=self.ZopeFind(self,obj_ids=[id])[0][1]
  333:             if obj.getSize()==0:
  334:                 self.REQUEST.SESSION['objID']=obj.getId()
  335:                 pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','errorUploadFile')).__of__(self)
  336:                 return pt()
  337: 
  338:             else:
  339:                 RESPONSE.redirect(self.REQUEST['URL2'])
  340: 
  341:         else:
  342:             return self.ZopeFind(self,obj_ids=[id])[0][1]
  343:         
  344:         
  345: def manage_addCDLIFileForm(self):
  346:     """interface for adding the OSAS_root"""
  347:     pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addCDLIFile.zpt')).__of__(self)
  348:     return pt()
  349: 
  350: def manage_addCDLIFile(self,id,title,lockedBy, author=None, RESPONSE=None):
  351:     """add the OSAS_root"""
  352:     newObj=CDLIFile(id,title,lockedBy,author)
  353:     self._setObject(id,newObj)
  354:    
  355:     if RESPONSE is not None:
  356:         RESPONSE.redirect('manage_main')
  357: 
  358: 
  359: 
  360: 
  361: def splitatf(fh,dir=None):
  362:     """split it"""
  363:     
  364:     nf=None
  365:     for line in fh.readlines():
  366:        
  367:         if (len(line.lstrip())>0) and (line.lstrip()[0]=="&"): #newfile
  368:             if nf:
  369:                 nf.close() #close last file
  370:         
  371:             
  372:             filename=line[1:].split("=")[0].rstrip()+".atf"
  373:             if dir:
  374:                 filename=os.path.join(dir,filename)
  375:             nf=file(filename,"w")
  376:             
  377:         nf.write(line)
  378:     
  379:     nf.close()
  380:     fh.close()
  381:     
  382: class CDLIFileFolder(versionedFileFolder):
  383:     """CDLI folder"""
  384:     
  385:     meta_type="CDLI Folder"
  386:     filesMetaType=['CDLI file']
  387:     folderMetaType=['CDLI Folder']
  388:     default_catalog='CDLICatalog'
  389:     
  390:     def uploadATF(self,upload,RESPONSE=None):
  391:         """upload an atf file"""
  392:         #TODO: add comments
  393:         #TODO: finish uploadATF
  394:         dir=mkdtemp()
  395:         changed=[]
  396:         errors=[]
  397:         newPs=[]
  398:         splitatf(upload,dir)
  399: 
  400:         for fn in os.listdir(dir):
  401:             founds=self.CDLICatalog.search({'path':fn})    
  402:             if len(founds)==0:
  403:                 newPs.append(fn)
  404:                 
  405:             for found in founds:
  406:                 obj=found.getObject()
  407:        
  408:                 if (not obj.lockedBy=='') and (not obj.lockedBy==self.REQUEST['AUTHENTICATED_USER']):
  409:                     errors.append(obj)
  410:                 else:
  411:                     data=file(os.path.join(dir,fn)).read()
  412:                     diffs=obj.diff(data)
  413:                     if diffs[0]>0:
  414:                         changed.append((obj,diffs))
  415:                         #hochladen
  416:         
  417:         self.REQUEST.SESSION['changed']=[x[0].getId() for x in changed]
  418:         self.REQUEST.SESSION['errors']=[x.getId() for x in errors]
  419:         self.REQUEST.SESSION['newPs']=newPs
  420:         self.REQUEST.SESSION['tmpdir']=dir
  421:         
  422:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadCheck.zpt')).__of__(self)
  423:         return pt(changed=changed,errors=errors,dir=dir,newPs=newPs)
  424:                     
  425:     def uploadATFfinally(self,procedure,comment="",unlock=None,RESPONSE=None):
  426:         """upload the files"""
  427:         
  428:         if procedure=="uploadchanged":
  429:             uploadFns=self.REQUEST.SESSION['changed']+self.REQUEST.SESSION['newPs']
  430:         
  431:         elif procedure=="uploadAll":
  432:             uploadFns=[]
  433:             for x in os.listdir(self.REQUEST.SESSION['tmpdir']):
  434:                 if not x in self.REQUEST.SESSION['errors']:
  435:                     uploadFns.append(x)
  436:         else:
  437:             uploadFns=[]
  438:             
  439:         for fn in uploadFns:
  440:             founds=self.CDLICatalog.search({'path':fn})
  441:             if len(founds)>0:
  442:                 self.REQUEST['author']=str(self.REQUEST['AUTHENTICATED_USER'])
  443:                 founds[0].getObject().manage_addCDLIFileObject('',comment,self.REQUEST['author'],file=file(os.path.join(self.REQUEST.SESSION['tmpdir'],fn)))
  444:             
  445:         
  446:                 
  447:         newPs=self.REQUEST.SESSION['newPs']
  448:         if len(newPs)>0:
  449:             tmpDir=self.REQUEST.SESSION['tmpdir']
  450:         
  451:             self.cdli_main.importFiles(comment=comment,author=str(self.REQUEST['AUTHENTICATED_USER']) ,folderName=tmpDir, files=newPs)
  452:                 
  453:         
  454:         
  455:         #unlock
  456:         if unlock:
  457:             unlockFns=[]
  458:             for x in os.listdir(self.REQUEST.SESSION['tmpdir']):
  459:                     if not x in self.REQUEST.SESSION['errors']:
  460:                         unlockFns.append(x)
  461:             
  462:             for fn in unlockFns:
  463:                 founds=self.CDLICatalog.search({'path':fn})
  464:                 if len(founds)>0:
  465:                     self.REQUEST['author']=str(self.REQUEST['AUTHENTICATED_USER'])
  466:                    
  467:                     founds[0].getObject().lockedBy=""
  468:                     
  469:         if RESPONSE is not None:
  470:             RESPONSE.redirect(self.aq_parent.absolute_url())
  471:         
  472: 
  473:     def findObjectsFromList(self,upload,RESPONSE):
  474:         """findObjectsFromList (, TAB oder LINE separated)"""
  475:         txt=upload.read()
  476:         txt=txt.replace(",","\n")
  477:         txt=txt.replace("\t","\n")
  478:         idsTmp=txt.split("\n")
  479:         ids=[]
  480:         for id in idsTmp: # make sure that no empty lines
  481:             idTmp=id.lstrip().rstrip()
  482:             if len(idTmp)>0:
  483:                 ids.append(idTmp)
  484:         #self.REQUEST.SESSION['ids']=" OR ".join(ids)
  485:         
  486:         RESPONSE.redirect("filelist.html?path=%s"%" OR ".join(ids))
  487:     
  488:     def createAllFilesAsSingleFile(self,RESPONSE=None):
  489:         """download all files"""
  490:         
  491:         def sortF(x,y):
  492:             return cmp(x[0],y[0])
  493:         
  494:         catalog=getattr(self,self.default_catalog)
  495:         #tf,tfilename=mkstemp()
  496:         
  497:         
  498:         list=[(x.getId,x) for x in catalog()]
  499:         list.sort(sortF)
  500:         
  501:         RESPONSE.setHeader("Content-Disposition","""attachement; filename=%s"""%"all.atf")
  502:         RESPONSE.setHeader("Content-Type","application/octet-stream")
  503:        
  504:         for l in list:
  505:             obj=l[1].getObject()
  506:             
  507:             if obj.meta_type=="CDLI file":
  508:                 
  509:                 #os.write(tf,obj.getLastVersion().data)
  510:                 if RESPONSE:
  511:                     RESPONSE.write(obj.getLastVersion().data)
  512:         #os.close(tf)
  513:         #RESPONSE.redirect(self.absolute_url()+"/downloadFile?fn="%tfilename)
  514:         return True
  515:     
  516:     def downloadFile(self,fn):
  517:         """download fn - not used yet"""
  518:         self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename=%s"""%self.getLastVersion().getId())
  519:         self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
  520:         self.REQUEST.RESPONSE.write(file(fn).read())
  521:         
  522:       
  523:                 
  524:     def hasParent(self):
  525:         """returns true falls subfolder"""
  526:       
  527:         if self.aq_parent.meta_type in self.folderMetaType:
  528:             return True
  529:         else:
  530:             return False
  531:         
  532:     def getFolders(self):
  533:         """get all subfolders"""
  534:         ret=[]
  535:         folders=self.ZopeFind(self,obj_metatypes=self.folderMetaType)
  536:         for folder in folders:
  537:             ret.append((folder[1],
  538:                         len(self.ZopeFind(folder[1],obj_metatypes=self.folderMetaType)),
  539:                         len(self.ZopeFind(folder[1],obj_metatypes=self.filesMetaType))
  540:                         ))
  541:         return ret
  542:     
  543:             
  544:     def getFolders_OLD(self):
  545:         """get all subfolders"""
  546:         ret=[]
  547:         folders=self.ZopeFind(self,obj_metatypes=self.folderMetaType)
  548:         for folder in folders:
  549:             ret.append((folder[1],
  550:                         len(self.ZopeFind(folder[1],obj_metatypes=self.folderMetaType)),
  551:                         len(getattr(self,self.default_catalog)({'path':folder[0]}))
  552:                         ))
  553:         return ret
  554:     
  555:     def index_html(self):
  556:         """main"""
  557:         ext=self.ZopeFind(self,obj_ids=["index.html"])
  558:         if ext:
  559:             return ext[0][1]()
  560:         
  561:         pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','CDLIFileFolderMain')).__of__(self)
  562:         return pt()
  563:     
  564:     def importFiles(self,comment="",author="" ,folderName="/Users/dwinter/Documents/workspace/cdli/atf", files=None):
  565:         """import files"""
  566:         
  567:         if not files:
  568:             files=os.listdir(folderName)
  569:             
  570:         for f in files:
  571:             folder=f[0:3]
  572:             f2=f[0:5]
  573:             obj=self.ZopeFind(self,obj_ids=[folder])
  574:             
  575:             if not obj:
  576:                 manage_addCDLIFileFolder(self,folder,folder)
  577:                 fobj=getattr(self,folder)
  578:         
  579:             else:
  580:                 fobj=obj[0][1]
  581:             
  582:             obj2=fobj.ZopeFind(fobj,obj_ids=[f2])
  583:         
  584:             if not obj2:
  585:                 manage_addCDLIFileFolder(fobj,f2,f2)
  586:                 fobj2=getattr(fobj,f2)
  587:         
  588:             else:
  589:                 fobj2=obj2[0][1]
  590:               
  591:             file2=file(os.path.join(folderName,f))   
  592:             id=f
  593:             manage_addCDLIFile(fobj2,f,'','')
  594:             id=f
  595:             ob=fobj2._getOb(f)
  596:             ob.title=id
  597:             
  598:             manage_addCDLIFileObject(ob,id,comment,author,file2,content_type='')
  599:             self.CDLICatalog.catalog_object(ob)
  600:             #self.CDLICatalog.manage_catalogFoundItems(obj_ids=[id],search_sub=1)
  601:             #self.CDLICatalog.manage_catalogObject(self.REQUEST, self.REQUEST.RESPONSE, 'CDLICatalog', urlparse.urlparse(ob.absolute_url())[1])
  602:             
  603:         return "ok"
  604:     
  605: manage_addCDLIFileFolderForm=DTMLFile('dtml/folderAdd', globals())
  606: 
  607:     
  608: def manage_addCDLIFileFolder(self, id, title='',
  609:                      createPublic=0,
  610:                      createUserF=0,
  611:                      REQUEST=None):
  612:     """Add a new Folder object with id *id*.
  613: 
  614:     If the 'createPublic' and 'createUserF' parameters are set to any true
  615:     value, an 'index_html' and a 'UserFolder' objects are created respectively
  616:     in the new folder.
  617:     """
  618:     ob=CDLIFileFolder()
  619:     ob.id=str(id)
  620:     ob.title=title
  621:     self._setObject(id, ob)
  622:     ob=self._getOb(id)
  623: 
  624:     checkPermission=getSecurityManager().checkPermission
  625: 
  626:     if createUserF:
  627:         if not checkPermission('Add User Folders', ob):
  628:             raise Unauthorized, (
  629:                   'You are not authorized to add User Folders.'
  630:                   )
  631:         ob.manage_addUserFolder()
  632: 
  633:   
  634:     if REQUEST is not None:
  635:         return self.manage_main(self, REQUEST, update_menu=1)
  636: 
  637: 

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