# -*- coding: utf-8 # $Id$ # # Copyright 2001, 2002 by IVA Team and contributors # # This file is part of IVA. # # IVA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # IVA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with IVA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """Contains class WebtopFolder, which represents a folder in a user's webtop.""" __version__ = "$Revision$"[11:-2] from copy import copy from urllib import quote_plus, quote import Globals import time from input_checks import is_valid_title, is_valid_url, strip_all, is_valid_id from WebtopItem import WebtopItem from WebtopLink import WebtopLink from WebtopMemo import WebtopMemo from WebtopFile import WebtopFile from Cruft import Cruft #import Webtop import OFS from OFS.ObjectManager import checkValidId import FLE from TempObjectManager import TempObjectManager from AccessControl import ClassSecurityInfo from AccessControl import getSecurityManager from common import translate from common import perm_view, perm_edit, perm_manage, perm_add_lo #since webtopfolder doesn't have acquisition. we import it for adding wiki:( #very stupid work-around from Acquisition import aq_base as aqbase from DateTime.DateTime import DateTime from Errors import FleError try: from Products.ZWiki.ZWikiPage import ZWikiPage USE_ZWIKI = 1 except: USE_ZWIKI = 0 import re from zope.interface import implements from interfaces import IWebtopFolder, IWebtopItem, IStatistics, IUserManager, IFLE from zope.component import getUtility from Products.PageTemplates.PageTemplateFile import PageTemplateFile # This class acts as a container to other WebtopItems and as the factory # object used to manipulate them. class WebtopFolder( WebtopItem, OFS.Folder.Folder, TempObjectManager, Cruft): """A folder in a Webtop.""" meta_type = "WebtopFolder" implements(IWebtopFolder, IWebtopItem) list_of_types=('WebtopFolder', 'WebtopLink', 'WebtopMemo', 'WebtopFile', 'GroupFolder', 'Portfolio', 'AssignmentProxy') security = ClassSecurityInfo() maintemplate = PageTemplateFile('browser/templates/main/wiki_macro.pt', globals()) def __init__(self, parent, name): """Construct the webtop folder object.""" WebtopItem.__init__(self,parent,name) self.set_icon('folder_gif.gif') # for ZCatalog security.declarePrivate('get_content') def get_content(self): """Return content (names of this folder's Webtop items in one string)""" tlist = ('WebtopFolder', 'WebtopLink', 'WebtopMemo', 'WebtopFile') if self.isFeatureEnabled('sqi'): tlist += ('WebtopProxyFile',) if self.isFeatureEnabled('scorm'): tlist += ('SCORMFile',) return ' '.join( [o.get_name() for o in self.objectValues(tlist)]) security.declareProtected(perm_view, 'has_content') def has_content(self): """Any WebtopItems in this folder?""" return len(self.objectIds(self.list_of_types)) > 0 security.declareProtected(perm_view, 'list_contents_request2') def list_contents_request2(self, REQUEST=None, only_folder='', criteria='getWeight', extra=(), relative='', showTree=False): """ get folder's contents """ cw = self.catalog_webtop_items this_rel = self.getRelativeURL(self) fle_rel = '/'+self.absolute_url(1) fle_root = self.fle_root() if relative: this_rel = relative fler = '/'.join(fle_root.getPhysicalPath()) this_rel = fler + '/' + this_rel + '/' sorder = 'getWeight' try: sorder = REQUEST.get('suund', 'getWeight') except AttributeError: pass if criteria != 'getWeight': sorder = criteria if self.isFeatureEnabled('sqi'): extra += ('WebtopProxyFile',) if self.isFeatureEnabled('scorm'): extra += ('SCORMFile',) if not only_folder: only_folder = self.list_of_types + extra q = {'meta_type': only_folder, 'path': this_rel, 'sort_on': sorder, 'sort_order': 'descending'} # XXX: NEED TO CHECK HERE IF WE HAVE TEACHER OR MANAGER/IVAADMIN. Should display stuff to them user = getSecurityManager().getUser() rolesInContext = user.getRolesInContext(self) add_vis = True for x in ('Manager', 'IVAAdmin', 'Teacher'): if x in rolesInContext: add_vis = False break if add_vis: q['visible'] = DateTime() #if 'fle_users' in this_rel and add_vis: # tmp = this_rel.split('/') # cnr = tmp[tmp.index('fle_users')+3][1:] # is_teacher = self.kas_opetaja(REQUEST, cnr) # if is_teacher: rolesInContext = rolesInContext + ['IVAAdmin', ] #q['allowedRolesAndUsers'] = rolesInContext + ['Anonymous', 'user:'+str(user)] rec = cw(q) res = [] if showTree: return rec for x in rec: burl = x.getURL(1) if burl == fle_rel: continue if burl.count('/') > fle_rel.count('/')+1: continue res.append(x) return res security.declareProtected(perm_view, 'list_contents_request') def list_contents_request(self, REQUEST, extra=()): "jarjestab vastavalt Request parameeetrile suund" if hasattr(REQUEST, 'suund'): return self.list_contents(criteria=REQUEST['suund'], extra=extra) else: return self.list_contents(criteria='weight', extra=extra) security.declareProtected(perm_view, 'list_contents') def list_contents(self, criteria='',only_folder='', extra=()): """Returns a list of all different WebtopItems in this folder.""" if criteria == '': criteria = 'date' if self.isFeatureEnabled('sqi'): extra += ('WebtopProxyFile',) if self.isFeatureEnabled('scorm'): extra += ('SCORMFile',) if only_folder: objs = self.objectValues(only_folder) else: objs = self.objectValues(self.list_of_types+extra) if criteria == 'name': d = {} names = [] for o in objs: name = o.get_name() names.append(name) d[name] = o names.sort() s_objs = [] for n in names: s_objs.append(d[n]) return s_objs elif criteria == 'size': d = {} sizes = [] for o in objs: # We append name in order to get unique keys # 10 digits should be enough for everybody. :-) size = '%010d' % o.get_size() + o.get_name() sizes.append(size) d[size] = o sizes.sort() s_objs = [] for n in sizes: s_objs.append(d[n]) return s_objs elif criteria == 'date': d = {} timestamps = [] for o in objs: # We append name in order to get unique keys try: timestamp = '%012.4f' % o.get_timestamp() + o.get_name() except AttributeError: # broken object! continue timestamps.append(timestamp) d[timestamp] = o timestamps.sort() timestamps.reverse() s_objs = [] for n in timestamps: s_objs.append(d[n]) return s_objs elif criteria == 'weight': d = {} sizes = [] for o in objs: if not hasattr(o,'weight'): o.weight = 1000 size = '%010d' % o.weight + o.get_id() sizes.append(size) d[size] = o sizes.sort() sizes.reverse() s_objs = [] for n in sizes: s_objs.append(d[n]) return s_objs else: raise 'FLE Error', 'Unknown sort criteria' security.declareProtected(perm_view, 'juhtLeht') def juhtLeht(self): """Kataloogi avaleht kokkupakitavasse arhiivi""" t="Kataloog" t=t+self.get_name()+"" return t security.declareProtected(perm_view, 'looArhiiv') def looArhiiv(self, REQUEST, arhiiv=None, tee=""): "Kataloogide ning alamkataloogide arhiveerimiseks." algus=0 import zipfile if arhiiv==None: import tempfile failinimi=tempfile.mktemp() arhiiv=zipfile.ZipFile(failinimi,"w",zipfile.ZIP_DEFLATED) algus=1 tee=tee+self.get_id()+"/" m=self.list_contents() kasIndeks=0 for x in m: if x.get_id()=="index.html": kasIndeks=1 if not kasIndeks: arhiiv.writestr(zipfile.ZipInfo(tee+"index.html"), self.juhtLeht()) for x in m: if x.meta_type=="WebtopFolder": x.looArhiiv(REQUEST, arhiiv, tee) if x.meta_type=="WebtopMemo": arhiiv.writestr(zipfile.ZipInfo(tee+x.get_id()+".txt"), x.get_body()) if x.meta_type=="WebtopFile": if x.has_realname(): arhiiv.writestr(zipfile.ZipInfo(tee+x.get_realname()), str(x.get_content())) else: arhiiv.writestr(zipfile.ZipInfo(tee+x.get_id()), str(x.get_content())) if algus: arhiiv.close() file = open(failinimi,"rb") export_data=file.read() file.close() import os os.remove(failinimi) REQUEST.RESPONSE.setHeader('content-type','application/zip') REQUEST.RESPONSE.setHeader('Content-disposition','attachment; filename=arhiiv.zip') return export_data security.declareProtected(perm_view, 'teePuu') def teePuu(self, REQUEST): from StringIO import StringIO out = StringIO() print >> out, "
" objs = self.list_contents_request2( only_folder = ('WebtopFolder','Portfolio','AssignmentProxy',), criteria='getWeight', showTree=True) base = self.getRelativeContentURL() + '/' struc = {} level = 0 while 1: had_items = False for x in objs: if not self.may_viewNG(REQUEST, x): continue ou = x.getRelativeContentURL.replace(base, '') if ou == x.getRelativeContentURL: continue if ou.count('/') == level: had_items = True parts = ou.split('/') d = struc for p in parts[:-1]: d = d.get(p) if level > 0: try: d = d.get('children') except AttributeError: break if d is not None: d[parts[-1]] = {'obj': x, 'children':{}} if not had_items: break level = level + 1 def printer(self, struc, level, out, idpref=None): keys = struc.keys() tmp = [] for k in keys: tmp.append([struc.get(k).get('obj').getWeight, k]) tmp.sort() tmp.reverse() if not idpref: idpref = "1" count = 1 for y in tmp: x = y[1] obj = struc.get(x).get('obj') name = obj.get_name if obj.meta_type == 'Portfolio': name = translate(self, 'Portfolio').encode('utf-8') #print >> out, " "*level, level, x, obj, obj.id, obj.get_name print >> out, " 0: print >> out, " style=\"display:none\" " print >> out, ">" if struc.get(x).has_key('children'): printer(self, struc.get(x)['children'], level+1, out, idpref+'-'+str(count)) count = count + 1 printer(self, struc, 0, out) print >> out, "
" print >> out, "
> out, " style=\"margin-left: "+str(level*1.5)+"em\" " print >> out, ">" print >> out, "> out, " onclick=\"toggleRows(this)\" style=\"background: url(++resource++images/f_plus.png) no-repeat\" " print >> out, ">" # XXX: request isn't available to brain anymore !? print >> out, ""+name+"" #print >> out, ""+name+"" print >> out, "
" return out.getvalue() security.declareProtected(perm_edit, 'laeArhiiv') def laeArhiiv(self, REQUEST, arhiiviandmed, html_to_wiki='', wikifolder_name='WikiHTML'): """ Arhiivi laadimine kataloogi """ import tempfile import OFS.Image failinimi=tempfile.mktemp() fail=open(failinimi, "w+b") fail.write(arhiiviandmed.read()) fail.close() import zipfile arhiiv=zipfile.ZipFile(failinimi, "r", zipfile.ZIP_DEFLATED) m=arhiiv.namelist() viga = "" if html_to_wiki: if not wikifolder_name: wikifolder_name = 'WikiHTML' wf = self.add_wiki(wikifolder_name, 1) for x in m: print "-->", x if html_to_wiki: if x.endswith('/'): continue if '/' in x: continue page_content = arhiiv.read(x) #page_name = x.split('.')[0].capitalize() page_name = x if page_name.endswith('.html'): #wikiobj = ZWikiPage(source_string='', __name__=page_name) wikiobj = ZWikiPage(source_string=page_content, __name__=page_name) #wikiobj._deleteOwnershipAfterAdd() #wikiobj.title='pealkiri' wf._setObject(page_name,wikiobj) wikiobj.setPageType('html') elif page_name.endswith('.jpg') or page_name.endswith('.gif') or page_name.endswith('.png'): # add image wf._setObject(page_name, OFS.Image.Image(page_name, page_name, page_content)) else: # add document wf._setObject(page_name, OFS.Image.File(page_name, page_name, page_content)) else: result = self.lisaFail(REQUEST, x, arhiiv) if not result: getUtility(IStatistics)._updateStat(REQUEST, 'uploadedFiles') else: viga += result import os os.remove(failinimi) return viga security.declareProtected(perm_edit, 'lisaFail') def lisaFail(self, REQUEST, failinimi, arhiiv=None): "Loob kataloogitee alates jooksvast kataloogist ning lõppu paigutab faili" kaust=self m=failinimi.split("/") vastus = "" for x in m[0:-1]: if not hasattr(kaust.aq_self, x): kaust.add_folder(x, x) kaust=getattr(kaust, x) try: checkValidId(kaust,m[-1],allow_dup=1) except: vastus += quote_plus(m[-1])+" - "+translate(self, 'Error: Invalid filename. Filename cannot contain spaces, punctuation symbols etc.')+"
" try: if not vastus: checkValidId(kaust,m[-1]) kaust.add_file(m[-1], arhiiv.read(failinimi), m[-1]) except: vastus += quote_plus(m[-1])+" - "+translate(self, 'Error: Filename is already in use.')+"
" return vastus security.declareProtected(perm_edit, 'add_wiki_handler') def add_wiki_handler( self, REQUEST, my_name, userLocation='', submit = '', # form buttons cancel = '', # ): """Handles the input from folder add form.""" my_name = strip_all(my_name) import string if my_name.upper() == 'WELCOME': return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title = 'Invalid name', message = 'This is a reserved name, please pick another name.', action = 'wt_add_wiki?my_name=%s' % quote_plus(my_name)) viga = 0 try: my_name = string.replace(my_name,my_name[0],my_name[0].upper(),1) except IndexError: viga =1 #if submit: if not cancel: if not is_valid_id(my_name) or viga: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message='Give valid name', action='wt_add_wiki?my_name=%s' % quote_plus(my_name)) if my_name in [o.get_name() for o in self.list_contents()]: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message=translate(self,"Name '%s' taken") % my_name, action='wt_add_wiki?name=%s' % quote_plus(my_name), my_name=my_name) if not USE_ZWIKI: return self.restrictedTraverse('message_dialog_error.html')( title='ZWiki unavailable', message="ZWiki is not installed.", action=self.absolute_url()) fold_obj = self.add_wiki(my_name) fold_obj.set_author(str(REQUEST.AUTHENTICATED_USER)) s = getUtility(IStatistics) if userLocation == 'Bookshelf': s._updateStat(REQUEST, 'modified_bookshelf') s._updateStat(REQUEST, 'createdWikis') elif cancel: pass else: # This code should never be reached. raise 'FLE Error', 'Unknown button' return REQUEST.RESPONSE.redirect(self.absolute_url()) security.declareProtected(perm_edit, 'add_folder_handler') def add_folder_handler( self, REQUEST, my_name, submit = '', # form buttons cancel = '', # ): """Handles the input from folder add form.""" my_name = strip_all(my_name) #if submit: if not cancel: if not is_valid_title(my_name): return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message='Give valid name', action='wt_add_folder?my_name=%s' % quote_plus(my_name)) if my_name in [o.get_name() for o in self.list_contents()]: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message=translate(self,"Name '%s' taken") % my_name, action='wt_add_folder?name=%s' % quote_plus(my_name), my_name=my_name) fold_obj = self.add_folder(my_name) fold_obj.set_author(str(REQUEST.AUTHENTICATED_USER)) elif cancel: pass else: # This code should never be reached. raise 'FLE Error', 'Unknown button' return REQUEST.RESPONSE.redirect(self.absolute_url()) def kasWikiKaust(self,REQUEST=None): """ kas tegemist on wiki kaustaga """ if hasattr(self,'wiki_kaust'): if self.wiki_kaust == 1: return 1 return 0 security.declareProtected(perm_view, 'wikiKaustEsimeneLeht') def wikiKaustEsimeneLeht(self,REQUEST=None): """ find ZWikiPage that has no parents """ lehenimi = "" count = 0 if hasattr(self,'_v_cached_first_name'): if hasattr(self, self._v_cached_first_name): if REQUEST: getUtility(IStatistics)._viewedObject(REQUEST, self.getRelativeURL(self)) return self._v_cached_first_name if len(self.objectValues('ZWiki Page'))>0: pass else: return "../" for obj in self.objectValues('ZWiki Page'): if obj.parents == [] or obj.parents[0] == '': lehenimi = obj.__name__ self._v_cached_first_name = lehenimi count = count +1 if not lehenimi: if hasattr(self.aq_inner.aq_self, self.get_name()): lehenimi = self.get_name() if lehenimi and REQUEST: getUtility(IStatistics)._viewedObject(REQUEST, self.getRelativeURL(self)) return lehenimi security.declarePrivate('aq_base') def aq_base(self): return self.aqbase security.declareProtected(perm_edit, 'add_wiki') def add_wiki(self,name, folder_only=0): from Products.ZWiki.ZWikiPage import ZWikiPage """Implementation of add_folder_handler without http code.""" # wt2 = Webtop('sahtel').__of__(self) f = WebtopFolder(self,name) f.wiki_kaust = 1 while hasattr(self.aq_self, f.id): f.id = self.generate_id() self._setObject(f.id,f) if folder_only: return f.__of__(self) wikiobj = ZWikiPage(source_string='', __name__=name) #wikiobj._deleteOwnershipAfterAdd() #wikiobj.title='pealkiri' f._setObject(name,wikiobj) wo = f.__of__(self) wo.manage_permission('Zwiki: Edit pages', ('User', ), 1) return wo security.declareProtected(perm_edit, 'add_folder') def add_folder(self,name,preferred_id=None): """Implementation of add_folder_handler without http code.""" f = WebtopFolder(self,name) if preferred_id: f.id = preferred_id while hasattr(self.aq_self, f.id): f.id = self.generate_id() self._setObject(f.id,f) return f.__of__(self) security.declareProtected(perm_edit, 'add_link_handler') def add_link_handler( self, REQUEST, my_name, url, type = '', userLocation='', submit = '', # form buttons cancel = '', # back_link = '', # 'add link to webtop' feature outside webtop ): """Handles the input from link add form.""" my_name = strip_all(my_name) if submit: if not is_valid_title(my_name): return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message='Give valid name', action='wt_add_link?my_name=%s&my_url=%s' % \ (quote_plus(my_name), quote_plus(url))) elif my_name in [o.get_name() for o in self.list_contents()]: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message=translate(self,"Name '%s' taken") % my_name, action='wt_add_link?my_name=%s&url=%s' % \ (quote_plus(my_name), quote_plus(url))) if not is_valid_url(url): return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid URL', message='Invalid URL', action='wt_add_link?my_name=%s&url=%s' % \ (quote_plus(my_name), quote_plus(url))) link_obj = self.add_link(my_name, url) s = getUtility(IStatistics) if userLocation == 'Bookshelf': s._updateStat(REQUEST, 'modified_bookshelf') s._updateStat(REQUEST, 'linksAdded') link_obj.set_author(str(REQUEST.AUTHENTICATED_USER)) elif back_link: if not is_valid_title(my_name): return self.restrictedTraverse('message_dialog.html')( self, REQUEST, title='Invalid name', message='Give valid name', action=back_link) # I think raise is more appropriate here because # if we have invalid name here, we have a _bug_ # and not an user error. --jmp 2002-02-20 raise 'FLE Error', 'Invalid name for link.' # If name already exists generate a new name... my_name = self.__build_name(my_name) link_obj = self.add_link(my_name,url,1) link_obj.set_author(str(REQUEST.AUTHENTICATED_USER)) if REQUEST: return self.restrictedTraverse('message_dialog.html')( self, REQUEST, title='Webtop link added', message='Added webtop %s link %s' % (type, my_name), action=back_link) else: return elif cancel: pass else: # This code should never be reached. raise 'FLE Error', 'Unknown button' if REQUEST: REQUEST.RESPONSE.redirect(self.absolute_url()) security.declarePrivate('add_link') def add_link(self,name,url_or_obj,internal=0): """Implementation of add_link_handler without http code.""" l = WebtopLink(self,name,url_or_obj,internal) while hasattr(self.aq_self, l.id): l.id = self.generate_id() self._setObject(l.id,l) return l.__of__(self) security.declareProtected(perm_edit, 'add_file_handler') def add_file_handler( self, REQUEST, my_name='', file=None, key = '', userLocation='', submit = '', # form buttons cancel = '', # ): """Handles the input from upload form.""" import Webtop nimetu=0 my_name = strip_all(my_name) # this is irritating. defaulting to submit if not submit and not cancel: submit = 1 if submit and file: quota = self.get_quota() if quota > 0: ui = getUtility(IUserManager).get_user_info(str(REQUEST.AUTHENTICATED_USER)) quota = quota * len(ui.user_courses()) message = '' if self.absolute_url().find('fle_users')>=0: if quota >= 0: # Quota in use? # Would we exceed the quota? if file and len(file.filename): file.seek(0, 2) size = self.find_class_obj(Webtop.Webtop).get_size() + \ file.tell() file.seek(0, 0) if size > quota: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Quota reached', message='Quota reached', action=self.absolute_url()) nimemassiiv=file.filename.split("\\") if len(my_name)==0: nimetu=1 my_name=nimemassiiv[-1] # Check name if not is_valid_title(my_name): message = translate(self,'Give valid name for ')+'. ' elif my_name in [o.get_name() for o in self.list_contents()]: message = translate(self,"Name '%s' taken") % my_name elif not is_valid_id(my_name) and nimetu: message = translate(self,'Give valid name')+'. ' # Check file if not key: if (not file) or len(file.filename) is 0: message += ' '+translate(self,'No files supplied') if message: if (not key) and file and len(file.filename) > 0: key = self.add_tmp_object(WebtopFile(self, 'spam', file)) if key: action = 'wt_upload?key=%s&my_name=%s' % \ (quote_plus(key), quote_plus(my_name)) else: action = 'wt_upload?my_name=%s' % quote_plus(my_name) return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Error', message=message, action=action) else: if key: f = self.remove_tmp_object(key) f.set_name(my_name) self._setObject(f.id,f) f.set_author(str(REQUEST.AUTHENTICATED_USER)) else: if nimetu: file_obj = self.add_file(nimemassiiv[-1], file, nimemassiiv[-1]) else: file_obj = self.add_file(my_name,file, nimemassiiv[-1]) file_obj.set_author(str(REQUEST.AUTHENTICATED_USER)) s = getUtility(IStatistics) if userLocation == 'Bookshelf': s._updateStat(REQUEST, 'modified_bookshelf') s._updateStat(REQUEST, 'uploadedFiles') elif cancel: if key: self.remove_tmp_object(key) else: # This code should never be reached. raise 'FLE Error', 'Unknown button' REQUEST.RESPONSE.redirect(self.absolute_url()) security.declarePrivate('add_file') def add_file(self, name, file, original_name=''): """Implementation of add_file_handler without http code.""" f = WebtopFile(self, name, file, original_name) while hasattr(self, f.id): f.id = self.generate_id() self._setObject(f.id,f) return f.__of__(self) security.declareProtected(perm_edit, 'add_memo_handler') def add_memo_handler( self, REQUEST, my_name, contents, course_id=0, userLocation='', submit='', cancel=''): """Handles the input from memo add form.""" my_name = strip_all(my_name) # this is irritating. defaulting to submit if not submit and not cancel: submit = 1 if submit: if not is_valid_title(my_name): return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message='Give valid name', action='wt_add_memo?my_name=%s&contents=%s' % \ (quote_plus(my_name), quote_plus(contents))) elif my_name in [o.get_name() for o in self.list_contents()]: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message=translate(self,"Name '%s' taken") % my_name, action='wt_add_memo?my_name=%s&contents=%s' % \ (quote_plus(my_name), quote_plus(contents)), my_name=my_name, contents=contents) else: memo_obj = self.add_memo(my_name,contents) memo_obj.set_author(str(REQUEST.AUTHENTICATED_USER)) s = getUtility(IStatistics) if userLocation == 'Bookshelf': s._updateStat(REQUEST, 'modified_bookshelf') s._updateStat(REQUEST, 'memosAdded') elif cancel: pass else: # This code should never be reached. raise 'FLE Error', 'Unknown button' REQUEST.RESPONSE.redirect(self.absolute_url()) security.declarePrivate('add_memo') def add_memo(self,name,contents): """Implementation of add_memo_handler without http code.""" m = WebtopMemo(self,name,contents) while hasattr(self, m.id): m.id = self.generate_id() self._setObject(m.id,m) return m.__of__(self) security.declareProtected(perm_edit, 'form_handler') def form_handler( self, item_ids=None, copy='', cut='', paste='', remove='', rename='', # submit buttons kalendrisse='', paki='', arhiivifail=None, lae='', REQUEST=None, cancel='', paki2='',userLocation='', html_to_wiki='', wikifolder_name=''): """Handles the input from folder default form: item copy/cut/paste, remove and rename operations.""" # Quota reached? (GroupFolders don't use quota.) import common if cancel: REQUEST.RESPONSE.redirect(self.absolute_url()) return try: quota_limit_reached = self.is_quota_limit_reached(REQUEST) except AttributeError: quota_limit_reached = 0 if not common.intersect_bool( ('GroupFolder',), [t[0].meta_type for t in self.list_parents_to_top()]) \ and quota_limit_reached and (copy or cut or paste): if REQUEST: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title=translate(self,'Quota reached'), message=translate(self,'Quota reached'), action=self.absolute_url()) else: raise 'FLE Error', \ "Can't copy/cut/paste when quota is reached." if item_ids is None and paste or paki or lae: if paste: self.pasteNG(REQUEST) elif paki: if paki2: return self.looArhiiv(REQUEST) else: REQUEST.RESPONSE.redirect('wt_manage.html?userLocation='+userLocation) return elif lae: tulem = self.laeArhiiv(REQUEST, arhiivifail, html_to_wiki, wikifolder_name) if userLocation == 'Bookshelf': getUtility(IStatistics)._updateStat(REQUEST, 'modified_bookshelf') if tulem: return self.restrictedTraverse('message_dialog_error.html')(self,REQUEST, title='Error: Some files failed!', message=tulem, width=600, align='left') return tulem elif item_ids: from types import StringType if type(item_ids) is StringType: item_ids=(item_ids,) objs = self.map_ids_to_objects(item_ids) if remove: return self.restrictedTraverse('message_dialog2.html')( self, title="Confirmation", message=translate(self,"Are you sure you want to delete these items: ").encode('utf-8') + ' ' + ', '.join([ci.get_name() for ci in objs]), handler = "remove_helper", extra_value_name="item_ids", extra_values=item_ids, option1_value="Cancel", option1_name="cancel", option2_value="Delete", option2_name="delete" ) elif copy: self.copy_n_cutNG(REQUEST, objs, 'copy') elif cut: self.copy_n_cutNG(REQUEST, objs, 'cut') elif kalendrisse: self.kalendrisse(REQUEST, objs) elif rename: REQUEST.set('item_ids',item_ids) return self.restrictedTraverse('wt_rename.html')() else: raise 'No action specified!' else: if REQUEST: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='No items selected', message='Select item first', action=self.absolute_url()) if not kalendrisse: REQUEST.RESPONSE.redirect(self.absolute_url()) security.declarePrivate('copy_n_cutNG') def copy_n_cutNG(self, REQUEST, items, operation='copy'): """ Saves items physical paths for later pasting """ locations = [] operation = 'iva_'+operation+'_items' for item in items: pp = item.getPhysicalPath() item_location = '/'.join(pp[1:]) #locations.append(item_location) locations.append(pp) REQUEST.SESSION.set('iva_cut_items', [] ) REQUEST.SESSION.set('iva_copy_items', [] ) REQUEST.SESSION.set(operation, locations) return 0 security.declareProtected(perm_edit, 'kalendrisse') def kalendrisse(self, REQUEST, items): "Viide sündmusena kalendrisse" import Kalender #XXX: which calendar? from Kalender import KalendriSyndmus k=self.getCalendar() esimene=None for e in items: s=e.absolute_url()[len(self.fle_root().absolute_url()):] nr=str(k.kysiUusNr()) s=KalendriSyndmus(e.get_name(), siseviide=s) s.id=nr k._setObject(nr, s) if esimene==None: esimene=s if esimene: REQUEST.RESPONSE.redirect(k.absolute_url()+"/"+nr+"/changeEvent.html") def __build_name(self,name, REQUEST): """Constructs a name for an item pasted from the clipboard. If the item's own name is already used, a suitable postfix is added.""" if not self.name_exists(name): return name iter = 1 newname=name+' ('+translate(self,'Copy1').encode('utf-8')+')' while self.name_exists(newname): iter += 1 newname=name+' ('+translate(self,'Copy2').encode('utf-8')+' ' + str(iter) + ')' return newname security.declarePrivate('do_pasting') def do_pasting(self, REQUEST, obj_url): """ gets old objects, makes copy and puts it in to new location """ olditem = self.restrictedTraverse(obj_url) newitem = olditem._getCopy(self) newitem.id = self.generate_id() newitem.set_name(self.__build_name(newitem.get_name(), REQUEST)) self._setObject(newitem.id, newitem) return olditem, newitem security.declarePrivate('pasteNG') def pasteNG(self, REQUEST): """ gets objects urls from iva_copy_items or/and iva_cut_items and pastes """ for obj_url in REQUEST.SESSION.get('iva_copy_items', []): self.do_pasting(REQUEST, obj_url) for obj_url in REQUEST.SESSION.get('iva_cut_items', []): olditem, newitem = self.do_pasting(REQUEST, obj_url) if olditem and newitem: oldfolder = olditem.parent() oldfolder._delObject(olditem.id) REQUEST.SESSION.set('iva_cut_items', [] ) #REQUEST.SESSION.set('iva_copy_items', [] ) return 0 security.declareProtected(perm_edit,'remove_helper') def remove_helper(self, REQUEST,item_ids, delete='', cancel=''): """ helps remove """ if cancel: return REQUEST.RESPONSE.redirect(self.absolute_url()) if delete: objs = self.map_ids_to_objects(item_ids) self.remove(objs) return REQUEST.RESPONSE.redirect(self.absolute_url()) security.declarePrivate('remove') # items: list of removable object references in current def remove(self,items): """Removes items from this folder, placing them in trash. Or actually: in the tmp_objects folder inside this WebtopFolder.""" for item in items: # self.move_to_tmp(item) self._delObject(item.get_id()) security.declareProtected(perm_edit, 'rename_handler') def rename_handler( self, REQUEST, item_id_list, new_name_list, submit = '', # form buttons cancel = '', # ): """Handles rename_form submission.""" if submit: bad_names = [] for name in new_name_list: if not is_valid_title(name): bad_names.append(name) if bad_names: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message=translate(self,'The following names are invalid:') + ' %s' % \ " ".join([repr(n) for n in bad_names]), action=self.absolute_url())#&names=%s'#% \ # (quote(repr(item_id_list)), # quote(repr(new_name_list)))) # Same name given for several object? new_names = list(copy(new_name_list)) new_names.sort() for i in range(len(new_names)-1): if new_names[i] == new_names[i+1]: return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message='You gave the same name for several objects.', action=self.absolute_url())# % \ # (quote(repr(item_id_list)), # quote(repr(new_name_list)))) # Some other object has already some given name? # FIXME: slow: 'not in' inside loop... names_in_use = [o.get_name() for o in \ filter(lambda x, y=item_id_list: \ x.get_id() not in y, self.list_contents())] bad_names = [] for name in new_name_list: if name in names_in_use: bad_names.append(name) if bad_names: REQUEST.set('item_ids',item_id_list) return self.restrictedTraverse('message_dialog_error.html')( self, REQUEST, title='Invalid name', message=translate(self,'The following names are already in use:') + ' %s' % \ " ".join([repr(n) for n in bad_names]), action=self.absolute_url())# \ # (quote(repr(item_id_list)), # quote(repr(new_name_list)))) for i in range(len(item_id_list)): (id, name) = (item_id_list[i], new_name_list[i]) self.rename(self.get_child(id), name) elif cancel: pass else: # This code should never be reached. raise 'FLE Error', 'Unknown button' REQUEST.RESPONSE.redirect(self.absolute_url()) security.declarePrivate('name_exists') def name_exists(self,name): """Checks whether a given name exists already in the folder.""" for item in self.objectValues(): if hasattr(item,'get_name'): if item.get_name()==name: return 1 return 0 security.declarePrivate('rename') # Input checks are done in rename_handler. def rename(self,objref,new_item_name): """Implementation of item rename.""" objref.set_name(new_item_name) objref.reindex_object() security.declareProtected(perm_view, 'get_size') def get_size(self): """Return size of the object.""" size = 0 for o in self.objectValues( ('WebtopFolder', 'WebtopLink', 'WebtopMemo', 'WebtopFile')): size += o.get_size() return size security.declareProtected(perm_view, 'lastModification') def lastModification(self, cnr=None): """Viimane muutus andmepuus""" if cnr: tmp = 0 try: tmp = getUtility(IStatistics).__of__(getUtility(IFLE)).getCourseStat(int(cnr), 'modified_bookshelf') except IndexError: pass tim = None try: tim = float(tmp) except TypeError: tim = float(0) return tim time = self.get_timestamp() return time security.declareProtected(perm_view, 'getWebtopRoot') def getWebtopRoot(self): """ return webtop """ if hasattr(self, 'toplevel'): return self while 1: x = self.aq_parent if x == self.fle_root(): return self if hasattr(x, 'toplevel'): return x security.declareProtected(perm_edit, 'add_portfolio') def add_portfolio(self): """ create portfolio """ import Portfolio o = Portfolio.Portfolio(self, 'Portfolio') self._setObject(o.id, o) return o.__of__(self) security.declareProtected(perm_edit, 'import_form_handler') def import_form_handler(self, REQUEST, file='', wikionly='', cancel='', course_import='', wiki_koht=''): """ import zwikis. wt_manage """ uname = REQUEST.AUTHENTICATED_USER.getUserName() right = 0 if file and wikionly and course_import and wiki_koht: right = 1 if not right: raise '' from ImportIMS import Importer import tempfile, os from StringIO import StringIO out = StringIO() koht=wiki_koht[len(self.fle_root().absolute_url()):].split('/') m = self.fle_root() for x in koht: if x: m = getattr(m, x) koht = m filename = tempfile.mktemp() f = open(filename,"w+b") f.write(file.read()) f.close() import_data=None jnr = None try: jnr = self.get_course_id_from_req(REQUEST) except AttributeError: jnr = self.get_jooksev_kursus() imported = Importer(uname,self.fle_root(),'',getattr(self.fle_root().courses, jnr),userwikionly=koht, out=out) imported.loadZip(filename) element = imported.loadFile('imsmanifest.xml') imported.processFile(self,element) os.remove(filename) return REQUEST.RESPONSE.redirect(wiki_koht) Globals.InitializeClass(WebtopFolder) # EOF