# -*- 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 IWebtopItem, IStatistics, IUserManager
from zope.component import getUtility
try:
from config import image_base
except ImportError:
image_base = ""
# 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(IWebtopItem)
list_of_types=('WebtopFolder', 'WebtopLink', 'WebtopMemo', 'WebtopFile', 'GroupFolder', 'Portfolio', 'AssignmentProxy')
security = ClassSecurityInfo()
security.declareProtected(perm_view, 'index_html')
def index_html(self, REQUEST=None):
""" webtop index """
if not self.hasPermissionToView(REQUEST):
return REQUEST.RESPONSE.redirect(REQUEST.HTTP_REFERER)
s = getUtility(IStatistics)
s._updateStat(REQUEST, 'foldersOpened')
id = self.getId()
if not (id[0]=='c' and id[1:].isdigit()) and id != 'gf':
s._viewedObject(REQUEST, self.getRelativeURL(self))
return REQUEST.RESPONSE.redirect(self.absolute_url()+'/wt_index_html')
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)
if relative:
this_rel = relative
fler = '/'.join(self.fle_root().getPhysicalPath())
this_rel = fler + '/' + this_rel + '/'
phys_rel = '/'.join(self.fle_root().getPhysicalPath()) + '/'
#print "THIS rel: ", this_rel
#print "FLE rel: ", fle_rel
#print "physical: ", phys_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 = []
#print rec
if showTree:
return rec
for x in rec:
#print x.get_author, x.getRelativeContentURL, x.getURL(1)
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
timestamp = '%012.4f' % o.get_timestamp() + o.get_name()
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()+""
m=self.list_contents()
for x in m:
t=t+"- "
if x.meta_type=="WebtopLink":
t=t+""+x.get_name()+""
if x.meta_type=="WebtopMemo":
t=t+""+x.get_name()+""
if x.meta_type=="WebtopFolder" or x.meta_type=="WebtopFile":
t=t+""+x.get_name()+""
t=t+"
\n"
t=t+"
"
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:
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(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', target=self.giveLanguage(REQUEST))
#print >> out, " "*level, level, x, obj, obj.id, obj.get_name
print >> out, " 0:
print >> out, " style=\"display:none\" "
print >> out, ">"
print >> out, " |
"
if struc.get(x).has_key('children'):
printer(struc.get(x)['children'], level+1, out, idpref+'-'+str(count))
count = count + 1
printer(struc, 0, out)
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:
if html_to_wiki:
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.', target=self.giveLanguage(REQUEST))+"
"
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.',target=self.giveLanguage(REQUEST))+"
"
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.message_dialog_error(
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.message_dialog_error(
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.message_dialog_error(
self, REQUEST,
title='Invalid name',
message=translate(self,"Name '%s' taken",target=self.giveLanguage(REQUEST)) % my_name,
action='wt_add_wiki?name=%s' % quote_plus(my_name),
my_name=my_name)
if not USE_ZWIKI:
return self.message_dialog_error(
title='ZWiki unavailable',
message="ZWiki is not installed.",
action="index_html")
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('index_html')
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.message_dialog_error(
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.message_dialog_error(
self, REQUEST,
title='Invalid name',
message=translate(self,"Name '%s' taken",target=self.giveLanguage(REQUEST)) % 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('index_html')
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)
return f.__of__(self)
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.message_dialog_error(
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.message_dialog_error(
self, REQUEST,
title='Invalid name',
message=translate(self,"Name '%s' taken",target=self.giveLanguage(REQUEST)) % 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.message_dialog_error(
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.message_dialog(
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.message_dialog(
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('index_html')
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)
if submit:
quota = self.get_quota()
if quota > 0:
ui = getattr(self.fle_root().fle_users, 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.message_dialog_error(
self, REQUEST,
title='Quota reached',
message='Quota reached',
action='index_html')
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 ',target=self.giveLanguage(REQUEST))+'. '
elif my_name in [o.get_name() for o in self.list_contents()]:
message = translate(self,"Name '%s' taken",target=self.giveLanguage(REQUEST)) % my_name
elif not is_valid_id(my_name) and nimetu:
message = translate(self,'Give valid name',target=self.giveLanguage(REQUEST))+'. '
# Check file
if not key:
if (not file) or len(file.filename) is 0:
message += ' '+translate(self,'No files supplied',target=self.giveLanguage(REQUEST))
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.message_dialog_error(
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('index_html')
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)
if submit:
if not is_valid_title(my_name):
return self.message_dialog_error(
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.message_dialog_error(
self, REQUEST,
title='Invalid name',
message=translate(self,"Name '%s' taken",target=self.giveLanguage(REQUEST)) % 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('index_html')
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('index_html')
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.message_dialog_error(
self, REQUEST,
title=translate(self,'Quota reached',target=self.giveLanguage(REQUEST)),
message=translate(self,'Quota reached',target=self.giveLanguage(REQUEST)),
action='index_html')
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?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.message_dialog_error(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.message_dialog2(
self, title="Confirmation",
message=translate(self,"Are you sure you want to delete these items: ",target=self.giveLanguage(REQUEST)) + ' ' + ', '.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.wt_rename(REQUEST)
else:
raise 'No action specified!'
else:
if REQUEST:
return self.message_dialog_error(
self, REQUEST,
title='No items selected',
message='Select item first',
action='index_html')
if not kalendrisse:
REQUEST.RESPONSE.redirect('index_html')
# FIXME: input_checks
security.declareProtected(perm_edit, 'rename_helper')
# This is called from wt_rename to convert a list stored in url
# back to list. There are two cases:
#
# 1. User select some object on index_html page and clicks 'rename':
#
# index_html(dtml) -> form_handler -> redirect to wt_rename(dtml)
#
# In this case only Ids of objects are passed to form_handler
#
#
# 2. As long user gives invalid input we are in the following loop:
#
# wt_rename -> rename_handler -> message_dialog(dtml) -> wt_rename
#
# Here we have pass user's invalid names back to wt_rename so
# that user doesn't have to start everytime from scratch.
def rename_helper(self, expr1, expr2=None):
"""Helper function for DTML method wt_rename.dtml"""
if not expr2:
return eval(expr1)
else:
id_list = eval(expr1)
name_list = eval(expr2)
retval = []
for i in range(len(id_list)):
retval.append((id_list[i], name_list[i]))
return retval
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")
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',target=self.giveLanguage(REQUEST))+')'
while self.name_exists(newname):
iter += 1
newname=name+' ('+translate(self,'Copy2',target=self.giveLanguage(REQUEST))+' ' + 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('index_html')
if delete:
objs = self.map_ids_to_objects(item_ids)
self.remove(objs)
return REQUEST.RESPONSE.redirect('index_html')
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.message_dialog_error(
self, REQUEST,
title='Invalid name',
message=translate(self,'The following names are invalid:',target=self.giveLanguage(REQUEST)) + ' %s' % \
" ".join([repr(n) for n in bad_names]),
action='index_html')#&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.message_dialog_error(
self, REQUEST,
title='Invalid name',
message='You gave the same name for several objects.',
action='index_html')# % \
# (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.message_dialog_error(
self, REQUEST,
title='Invalid name',
message=translate(self,'The following names are already in use:',target=self.giveLanguage(REQUEST)) + ' %s' % \
" ".join([repr(n) for n in bad_names]),
action='index_html')# \
# (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('index_html')
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)
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).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