# -*- 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 """This is the main module for FLE, containing the FLE class and the Zope factory method for creating a FLE installation inside Zope.""" __version__ = "$Revision$"[11:-2] from config import IVA_VERSION try: from config import image_base except ImportError: image_base = "" import os.path, string, time try: from PIL import Image PIL_imported = 1 except ImportError: PIL_imported = 0 try: from Products.PlacelessTranslationService import getTranslationService PLACELESS = 1 except ImportError: PLACELESS = 0 try: from Products.ZWiki.ZWikiPage import ZWikiPage ZWIKI_imported = 1 except ImportError: ZWIKI_imported = 0 try: from Products.ZMySQLDA.DA import Connection SQL_INSTALLED = 1 except ImportError: SQL_INSTALLED = 0 import Globals from Products.PageTemplates.PageTemplateFile import PageTemplateFile from Products.StandardCacheManagers import AcceleratedHTTPCacheManager from Globals import Persistent, Acquisition, HTMLFile, PersistentMapping import AccessControl import OFS from OFS.Folder import Folder from Products.ZCatalog.ZCatalog import ZCatalog from TraversableWrapper import TraversableWrapper as TW from Cruft import Cruft from ThinkingTypeSetManager import ThinkingTypeSetManager as TTSM from UserManager import UserManager from CourseManager import CourseManager from Timer import Timer from common import file_path, translate import Acquisition import YlTest from string import atoi from common import perm_view, perm_edit, perm_manage, perm_add_lo, perm_access, \ roles_admin, roles_staff, roles_user import common import re import YlHoidla from YlHoidla import YlHoidla from zope.interface import implements from interfaces import IFLE from zope.component import adapter from zope.app.container.interfaces import IObjectAddedEvent try: from Products.CMFCore.CookieCrumbler import CookieCrumbler, ATTEMPT_NONE, ATTEMPT_LOGIN, ATTEMPT_RESUME CCAware = 1 except: CCAware = 0 from Products.CMFCore.PortalObject import PortalObjectBase as SkinnableObjectManager from OFS.OrderSupport import OrderSupport from zope.interface import implements from Products.iva.interfaces.siteroot import IIVASiteRoot from Products.Five.component.interfaces import IObjectManagerSite from zope.event import notify from zope.app.publication.zopepublication import BeforeTraverseEvent from OFS.Folder import manage_addFolder # This is the class for the FLE installation root object. class FLE( SkinnableObjectManager, Folder, TW, Cruft, Persistent, AccessControl.Role.RoleManager, OFS.SimpleItem.Item, Timer, OrderSupport, ): """FLE product.""" security = AccessControl.ClassSecurityInfo() security.declareObjectPublic() meta_type = 'IVA' implements(IFLE) has_order_support = 0 security.declareProtected(perm_manage, 'management_tab') # management_tab = Globals.DTMLFile('ui/FLE/management_tab', globals()) management_tab = PageTemplateFile('ui/management_tab', globals()) management_tab._owner = None manage_options=( {'label' : 'Tools', 'action' : 'management_tab'}, ) + OFS.Folder.Folder.manage_options # NOTE: Since we use a python method index_html to do # the redirection to the appropriate DTML method, EVERY FOLDER # that the user access must have this index_html method # (either through class inheritance or as its own dtml method, # but not through acquisition from its containers). Acquisition # cannot be used, since the object reference passed to the DTML # method will point to the object where index_html was acquired. # So all courses, contexts, notes, userinfos, webtops and webtopfolders # and any other folderish objects must have this python method. security.declarePublic('index_html') def index_html(self,REQUEST): """ index_html """ return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/start_page') # Parameters are received from the creation form at # ui/FLE/creation_form.dtml def __init__( self, _id, title, smtp_host, smtp_port=25, _default_lang='en', _quota=3000000, mfrom='iva@htk.tlu.ee', def_passwd=0,def_not_change=0,def_not_aff=0): """Construct FLE object.""" self.setup_timer() errors = [] if not _id: errors.append('ID not specified') if not title: errors.append('Title not specified') if errors: raise 'Insufficient form data',str(errors) self.id = _id self._default_lang=_default_lang self._quota=_quota self.title = title self.mfrom = mfrom self.def_asswd= int(def_passwd) self.def_ot_change= int(def_not_change) self.def_ot_aff= int(def_not_aff) self._pending_users = PersistentMapping() # user list self.__fle_root = '' if len(smtp_host)>0 and smtp_port: from Products.SecureMailHost import SecureMailHost mailhost = SecureMailHost.SecureMailHost('MailHost', smtp_host=smtp_host, smtp_port=int(smtp_port)) self._setObject('MailHost', mailhost) # ZCatalog for webtop items catalog = ZCatalog('catalog_webtop_items', 'ZCatalog for webtop items') self._setObject('catalog_webtop_items', catalog) catalog = self.catalog_webtop_items # indexes catalog.addIndex('allowedRolesAndUsers', 'KeywordIndex') catalog.addIndex('getObjPermission', 'FieldIndex') catalog.addIndex('getWeight', 'FieldIndex') catalog.addIndex('get_name', 'FieldIndex') catalog.addIndex('get_size', 'FieldIndex') catalog.addIndex('get_timestamp', 'FieldIndex') catalog.addIndex('meta_type', 'KeywordIndex') #catalog.addIndex('get_content', 'TextIndex') # indexing binary data would be stupid class largs: def __init__(self, **kw): self.__dict__.update(kw) catalog.addIndex('get_author', 'FieldIndex') catalog.addIndex('path', 'IVAPathIndexNG') class DRattrs: since_field='getStartTimeIndex' until_field='getEndTimeIndex' catalog.addIndex('visible', 'DateRangeIndex', DRattrs()) from Products.ZCTextIndex.ZCTextIndex import manage_addLexicon manage_addLexicon(catalog, 'lexicon', elements=[ largs(group= 'Case Normalizer' , name= 'Case Normalizer' ), largs(group= 'Stop Words', name= " Don't remove stop words" ), largs(group= 'Word Splitter' , name= "IVA Unicode Whitespace splitter" ), ] ) class attrs: doc_attr = 'get_name' lexicon_id = 'lexicon' index_type = 'Cosine Measure' catalog.addIndex('fulltext', 'ZCTextIndex', attrs()) # metadata catalog.addColumn('absolute_url') catalog.addColumn('getRelativeContentURL') catalog.addColumn('getTitle') catalog.addColumn('getWeight') catalog.addColumn('get_author') catalog.addColumn('get_icon_path') catalog.addColumn('get_id') catalog.addColumn('get_name') catalog.addColumn('get_size') catalog.addColumn('get_timestamp') catalog.addColumn('kasWikiKaust') catalog.addColumn('lastModification') catalog.addColumn('meta_type') #self._setObject('catalog_webtop_items', catalog) # ZCatalog for events catalog = ZCatalog('catalog_events','ZCatalog for events') # indexes catalog.addIndex('meta_type', 'FieldIndex') catalog.addIndex('path', 'IVAPathIndexNG') catalog.addIndex('kysiOlek', 'FieldIndex') catalog.addIndex('getName', 'FieldIndex') catalog.addIndex('asukohaNimi', 'FieldIndex') catalog.addIndex('get_start_time', 'DateIndex') catalog.addIndex('get_end_time', 'DateIndex') # metadata catalog.addColumn('getName') catalog.addColumn('kysiOlek') catalog.addColumn('getContent') catalog.addColumn('kysiSiseviide') catalog.addColumn('kysiViide') catalog.addColumn('kysiAlgus') catalog.addColumn('kysiLopp') catalog.addColumn('get_start_time') catalog.addColumn('get_end_time') catalog.addColumn('absolute_url') catalog.addColumn('meta_type') # add object self._setObject('catalog_events', catalog) # blogs zcatalog self.add_blogs_zcatalog() from Products.Five.component import enableSite enableSite(self) security.declarePrivate('add_blogs_zcatalog') def add_blogs_zcatalog(self): """ add catalog for blog entries """ # ZCatalog for blogs catalog = ZCatalog('blogs_zcatalog', 'ZCatalog for blogs') class largs: def __init__(self, **kw): self.__dict__.update(kw) from Products.ZCTextIndex.ZCTextIndex import manage_addLexicon manage_addLexicon(catalog, 'lexicon', elements=[ largs(group= 'Case Normalizer' , name= 'Case Normalizer' ), largs(group= 'Stop Words', name= " Don't remove stop words" ), largs(group= 'Word Splitter' , name= "IVA Unicode Whitespace splitter" ), ] ) class attrs: doc_attr = 'getTitle, getContent, getIntro' lexicon_id = 'lexicon' index_type = 'Cosine Measure' catalog.addIndex('fulltext', 'ZCTextIndex', attrs()) #indexes catalog.addIndex('meta_type', 'FieldIndex') catalog.addIndex('getNumberOfComments', 'FieldIndex') catalog.addIndex('getID', 'FieldIndex') catalog.addIndex('getTitle', 'FieldIndex') catalog.addIndex('getIntro', 'FieldIndex') catalog.addIndex('getContent', 'FieldIndex') catalog.addIndex('getAuthor', 'FieldIndex') catalog.addIndex('getTime', 'FieldIndex') catalog.addIndex('path', 'IVAPathIndexNG') #metadata catalog.addColumn('absolute_url') catalog.addColumn('getNumberOfComments') catalog.addColumn('getID') catalog.addColumn('getTitle') catalog.addColumn('getIntro') catalog.addColumn('getContent') catalog.addColumn('getAuthor') catalog.addColumn('get_author') catalog.addColumn('get_timestamp') catalog.addColumn('getTime') #add object self._setObject('blogs_zcatalog', catalog) # def manage_beforeDelete(self, item, container): # """ remove yourself from scheduler """ # #rename stats files # #XXX: remove sql tables # import os security.declareProtected(perm_manage, 'reload_typesets') def reload_typesets(self,REQUEST=None): """Reload typesets.""" self.typesets.load_default_sets() if REQUEST: return self.message_dialog( self, REQUEST, title='Reloaded', message='Knowledge type sets reloaded', action='index_html') security.declareProtected(perm_manage, 'reload_all') def reload_all(self, REQUEST=None): """Reload all dtml, style sheet, image, printer, and translation files.""" self.IVA_VERSION = IVA_VERSION self.reload_typesets() self.reload_images() if REQUEST: return self.message_dialog( self, REQUEST, title='Reloaded', message='Reloaded all knowledge type sets', action='index_html') security.declareProtected(perm_manage, 'reload_images') def reload_images(self, REQUEST=None): """ relaod images. Only used for frontpage images """ import os image_file_path = os.path.join(file_path, 'ui', 'images') self.add_images(self.images, image_file_path) getattr(self.images, 'frontpage').manage_permission(perm_view, ('Anonymous',) ,1) if REQUEST: return self.message_dialog( title = 'Reloaded', message = 'Images reloaded', action = 'index_html') def add_images(self, zope_path, file_path): """ add image to images folder """ for e in os.listdir(file_path): full_path = os.path.join(file_path, e) if os.path.isdir(full_path): if e == 'CVS': continue if e == '.svn': continue try: manage_addFolder(zope_path, e, '') except: pass self.add_images(getattr(zope_path, e), full_path) else: # title (3rd parameter) will be used as an alt parameter # inside HTML tag. (Override in DTML code when you # want some alt text (i.e. almost always...)) # This can be like this for now .... -granbo import re m = re.match("^(.*)\.", e) f = open(full_path,"rb") content = f.read() f.close() try: zope_path.manage_addImage(m.group(1), content, '') except: zope_path._delObject(m.group(1)) zope_path.manage_addImage(m.group(1), content, '') img = getattr(zope_path, m.group(1)) img.ZCacheable_setManagerId('HTTPCache') security.declarePublic('get_version') def get_version(self): """ return IVA version """ return getattr(self, 'IVA_VERSION', 'IVA') # FIXME: What should we do if self.webtop_quota_amount is invalid? security.declareProtected(perm_view, 'get_quota') def get_quota(self): """Return quota limit in bytes (-1 if no quota in use).""" if not hasattr(self, 'webtop_quota'): return -1 if not hasattr(self, 'webtop_quota_amount'): return -1 if not self.webtop_quota: return -1 # no quota s = self.webtop_quota_amount.strip() if s[-1].lower() == 'k': return int(s[:-1]) * 1024 elif s[-1].lower() == 'm': return int(s[:-1]) * 1024 * 1024 else: return int(s) #XXX: security check! # security.declareProtected(perm_view, 'get_languages') security.declarePublic('get_languages') def get_languages(self): """ return list of languages available """ lang_list = ['et','en','fi','ru', 'de'] return lang_list def get_default_language(self): "Vaikimisi keel" return getattr(self, 'default_language', 'en') # This is used by message_dialog.dtml. def message_dialog_handler(self, action, REQUEST): """Redirects to the given URL, preserving the state information in the url.""" REQUEST.RESPONSE.redirect(action) def _redirect_checks(self, REQUEST): """ redirect checks """ uname = str(REQUEST.AUTHENTICATED_USER) if (not hasattr(self.fle_users.aq_self, uname)): result = self.fle_users.add_user_fle(uname, ('Member',)) user = self.fle_users.get_user_info(uname) if self.getUseFinger(): user.fingerNames() #jnr = user.get_jooksev_kursus() self.courses.change_course(REQUEST, '0') return user security.declareProtected(perm_view, 'redirect_to_webtop') def redirect_to_webtop(self, REQUEST): """Redirect to webtop.""" user = self._redirect_checks(REQUEST) uname = user.get_uname() if user.get_first_name()=='' or user.get_last_name()=='': return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/fle_users/' + uname + '/webtop/edit_user_form') if hasattr(user, 'perm_must_change'): if user.perm_must_change == 1: return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/fle_users/' + uname + '/webtop/edit_user_form') else: return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/organizer_index') else: return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/organizer_index') security.declareProtected(perm_view, 'redirect_to_management') def redirect_to_management(self, REQUEST): """ redirect to management """ user = self._redirect_checks(REQUEST) return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url() + '/manage_iva_setup') security.declareProtected(perm_manage, 'manage_workspace') def manage_workspace(self,REQUEST): """This makes sure that ZCatalog doesn't override manage_workspace and make it point to index_html, when we actually want manage_main""" REQUEST.RESPONSE.redirect('manage_main') def logout(self,REQUEST): """This is the logout instruction page.""" return self.message_dialog2( self, REQUEST, title= 'Logout', message="To log out, either close your browser or press the Logout button below. When your browser asks for a username and password, just press Cancel. This will clear your login information from your browser's cache", extra_value_name = '', extra_values = (), option1_value = 'Cancel', option1_name = 'cancel', option2_value = 'Logout', option2_name = 'logout', handler = 'clear_password') security.declarePublic('clear_password') def clear_password( self, cancel=None, logout=None, REQUEST=None): """This will clear the password cache.""" if logout: #XXX: take care of session somehow, invalidating doesn't seem to work #REQUEST.SESSION.invalidate() REQUEST.RESPONSE.setStatus(401) REQUEST.RESPONSE.setHeader("WWW-Authenticate", 'basic realm="Zope"') try: self.login.logout() except AttributeError: pass return self.message_dialog( self, REQUEST, title='Logout', message='You have been logged out.', action = 'index_html') else: return self.redirect_to_webtop(REQUEST) def has_PIL(self): """Has the system PIL (Python Image Library) installed?""" return PIL_imported def has_PLACELESS(self): """ is PlacelessTranslationService installed? """ return PLACELESS def has_MySQL(self): return SQL_INSTALLED def getId(self): """ Return object id. Hack XXX """ return self.id security.declarePublic('register_form_handler') def register_form_handler(self, REQUEST, regB='', cancelB='', # buttons username='', fname='', lname='', email='', preflang='en',optmess='', numbercheck=0): """ registers user """ if regB and self.get_allow_autoregister(): ok = 1 inv_val = '' if username and fname and lname and email: ok = 1 if not '@' in email and not '.' in email: ok = 0 inv_val+= ' email' else: #XXX check email!? pass if not fname: ok = 0 if inv_val: inv_val+=',' inv_val+=' first name' if not lname: ok = 0 if inv_val: inv_val+=',' inv_val+=' last name' if numbercheck != REQUEST.SESSION.get('securenr'): ok = 0 if inv_val: inv_val+=',' inv_val+= ' number' if not username: ok = 0 if inv_val: inv_val+=',' inv_val+=' username' else: if self.fle_users.is_valid_uname(username): ok = 0 if inv_val: inv_val+=',' inv_val+=' username' # XXX: maybe we don't want that! # XXX: also check in fle_users folder for user record # XXX: check for lowlevel acl_users? if not ok: return self.register_form(username=username, fname=fname, lname=lname, email=email, optmess=optmess,mess='invalid values: '+inv_val) #do queueing self._queue_user(username=username, fname=fname, lname=lname, email=email, preflang=preflang,optmess=optmess) #XXX: subject of email. Translation! message = translate(self,"registrant_waiting", target=preflang) if self.saadaEmail(email,'useraccount request', message): return translate(self,"You have been registered, check e-mail",target=self.giveLanguage(REQUEST)) else: return translate(self,"You have been registered but some problems occured when sending email.",target=self.giveLanguage(REQUEST)) elif cancelB: return REQUEST.RESPONSE.redirect('index_html') raise "IVA Error", "unknown button in register_form_handler" def lostPassword(self,REQUEST, send=0,knimi='', give_email=0): if give_email: res = 1 if not knimi: res = 0 try: kasutaja = self.fle_users.get_user_info(knimi) except: res = 0 if kasutaja is None: return 0 if kasutaja.get_email() != '': res = 1 else: res = 0 if self.def_not_change: res = 0 if kasutaja.getSetting('perm_pass'): res = 0 return res #if not hasattr(self.aq_self,'MailHost'): if not getattr(self.aq_base, 'MailHost', None): return "" if send: try: kasutaja = self.fle_users.get_user_info(knimi) except: return 0 if kasutaja.get_email() == '': return 0 lang = self.giveLanguage(REQUEST) if lang not in self.get_languages(): lang = None sisu = '' #\nContent-Type:text/plain; charset=utf-8\n\n\n' sisu += "\n"+translate(self,'Message from IVA server',target=lang) sisu += "\n"+translate(self,'IVA server address:',target=lang)+" "+self.fle_root().absolute_url() sisu += "\n"+translate(self,'Username:',target=lang)+" "+knimi sisu += "\n"+translate(self,'Password:',target=lang)+" " new_pass = self.fle_users.looParool() try: kasutaja.set_password(new_pass) sisu += new_pass except: sisu += translate(self,"Error fetching password",target=lang) self.saadaEmail(kasutaja.get_email(),translate(self, 'Lost password', target=lang),sisu, kasutaja.get_email()) return "Recover password" security.declarePublic('randomImage') def randomImage(self): """ chooses 3/4 images to place on frontpage """ imgs = self.images.frontpage.objectValues() from random import shuffle shuffle(imgs) if self.get_allow_autoregister(): count=3 else: count = 4 if self.def_not_change: count += 1 return imgs[0:count] security.declareProtected(perm_manage,'manage_iva_setup_pictures') def manage_iva_setup_pictures(self, REQUEST, uploadB='', deleteB='',dele='', newimage=''): """ upload picture, delete picture """ imgContainer = getattr(self.images, 'frontpage') if deleteB: from types import StringType if type(dele) == StringType: dele = (dele,) for x in dele: imgContainer._delObject(x) if uploadB and newimage: import random nid = "" for x in range(15): nr = 95 while 900 and smtp_port: from Products.SecureMailHost import SecureMailHost mailhost = SecureMailHost.SecureMailHost('MailHost', smtp_host=smtp_host, smtp_port=int(smtp_port)) self._setObject('MailHost', mailhost) else: if len(smtp_host)>0 and smtp_port: mailhost = getattr(self, 'MailHost') mailhost.smtp_host = smtp_host mailhost.smtp_port = smtp_port self.MFROM = mailfrom self.def_passwd = def_passwd self.def_not_change = def_not_change self.def_not_aff = def_not_aff self.setUseFinger(useFinger) self.setFingerHost(fingerHost) self.setFingerPort(fingerPort) self.setSQLSettings(REQUEST.get('sql')) return self.manage_iva_setup(mess='settings saved succesfully!') return security.declareProtected(perm_manage, 'unqueue_user') def unqueue_user(self, uname): del self._pending_users[uname] security.declarePrivate('_queue_user') def _queue_user(self,username='', fname='', lname='', email='', preflang='en',optmess=''): # _pending_users if not getattr(self.aq_base, '_pending_users', None): self._pending_users = PersistentMapping() #if not hasattr(self.aq_self, '_pending_users'): # self._pending_users = PersistentMapping() while self._pending_users.has_key(username): username+='x' self._pending_users[username] = {'fname':fname,'lname':lname,'email':email,'preflang':preflang,'optmess':optmess} security.declareProtected(perm_manage,'get_pending_users') def get_pending_users(self): """ get pending users """ return self._pending_users.keys() security.declareProtected(perm_manage,'get_pending_details') def get_pending_details(self, uname): """ get details of pending user """ return self._pending_users[uname] security.declarePrivate('make_random_number') def make_random_number(self, REQUEST): # generates number and stores in in SESSION import random rnr = int(random.random()*10000000) REQUEST.SESSION.set('securenr',rnr) return rnr def get_allow_autoregister(self): return self.Autoregister security.declarePublic('generate_picture') def generate_picture(self, REQUEST, RESPONSE): """ test""" srnr = self.make_random_number(REQUEST) import PIL from PIL import Image, ImageDraw import cStringIO s = cStringIO.StringIO() pilt = Image.new('RGB',(100,30),(255,255,255)) pil2 = ImageDraw.Draw(pilt) tekst = str(srnr) pil2.text((10,10),tekst,fill=(30,30,128)) pilt.save(s,'jpeg') s.seek(0) RESPONSE.setHeader('Content-Type','image/jpeg') return s.read() security.declareProtected(perm_manage,'exportIMail') def exportIMail(self,REQUEST): """ export mailmessages """ from ExportIMS import Kirjutus from ExportIMS import kirjutaYldM import tempfile, os name = 'ivamessages.zip' path = os.path.join(Globals.INSTANCE_HOME,'var') fname = os.path.join(path,name) #fname = tempfile.mktemp() yld = kirjutaYldM() yld.kirjutaYldmanifest('innermail','Innermail messages',base='',href='messages.xml') yld.lisaFaili(fname) k = Kirjutus(self.fle_root(), self.get_id()) k.exportMail(fname) #os.remove(fname) return "Done! Zip-file is located at %s" % fname security.declareProtected(perm_manage, 'exportServerSettings') def exportServerSettings(self, REQUEST): """ export server settings and course categories """ from ExportIMS import Kirjutus from ExportIMS import kirjutaYldM import tempfile, os name = 'iva_settings.zip' path = os.path.join(Globals.INSTANCE_HOME,'var') fname = os.path.join(path,name) yld = kirjutaYldM() yld.kirjutaYldmanifest('IVA_C','IVA course categories',base='',href='course_cat.xml') yld.kirjutaYldmanifest('IVA_S','IVA server settings',base='',href='settings.xml') yld.kirjutaYldmanifest('IVA_A','IVA affiliation codes',base='',href='affiliations.xml') yld.lisaFaili(fname) k = Kirjutus(self.fle_root(), self.get_id()) k.looKursuseFail(0) #... do stuff k.exportCourseCategories(fname) k.exportServerSettings(fname) k.exportAffiliations(fname) return "Done! Zip-file is located at %s" % fname security.declareProtected(perm_manage,'exportICAL') def exportICAL(self,REQUEST): """ export user events """ from ExportIMS import Kirjutus from ExportIMS import kirjutaYldM import tempfile, os name = 'iva_events.zip' path = os.path.join(Globals.INSTANCE_HOME,'var') fname = os.path.join(path,name) #fname = tempfile.mktemp() yld = kirjutaYldM() yld.kirjutaYldmanifest('IVA','IVA user events',base='IVA/',href='imsmanifest.xml') # yld.kirjutaYldmanifest() yld.lisaFaili(fname) k = Kirjutus(self.fle_root(), self.get_id()) k.looKursuseFail(0) k.kirjutaKasutajaSyndmus(self.fle_users.get_users()) k.pakiKursusFaili(fname) #os.remove(fname) return "Done! Zip-file is located at %s" % fname security.declareProtected(perm_view,'getUseFinger') def getUseFinger(self): """ return if user information should be pulled via finger """ if not hasattr(self, 'useFinger'): return 0 return self.useFinger security.declareProtected(perm_manage,'setUseFinger') def setUseFinger(self, state): """ set if we should use finger """ self.useFinger = int(state) security.declareProtected(perm_view,'getFingerPort') def getFingerPort(self): """ return finger port """ if not hasattr(self, 'fingerPort'): return "79" return self.fingerPort security.declareProtected(perm_manage,'setFingerPort') def setFingerPort(self, port): """ set finger daemon port """ self.fingerPort = int(port) security.declareProtected(perm_view,'getFingerHost') def getFingerHost(self): """ return finger daemon host """ if not hasattr(self, 'fingerHost'): return "" return self.fingerHost security.declareProtected(perm_manage,'setFingerHost') def setFingerHost(self, host): """ set fingerdaemon host """ self.fingerHost = host def isWikiInstalled(self): return ZWIKI_imported security.declareProtected(perm_manage, 'setSQLSettings') def setSQLSettings(self, val): """ set sql values """ import transaction, re if val.get('password') == 'changeme': return if not val.get('database'): return if hasattr(self, 'iva_mysql_connection'): self._delObject('iva_mysql_connection') import re con_templ = '_DATABASE__HOSTNAME__PORT_ _USERNAME_ _PASSWORD_ _SOCKET_' db_pref = '' for key in val.keys(): pref = '' keyval = val.get(key) if key == 'table_prefix': db_pref = keyval if key == 'hostname': pref = '@' if key == 'port': pref = ':' con_templ = re.sub('_'+key.upper()+'_', pref+keyval, con_templ) con = re.sub('_.*?_', '', con_templ) self.manage_addProduct['ZMySQLDA'].manage_addZMySQLConnection( 'iva_mysql_connection', 'MySQL Connection', con, 'YES') # connect automatically self._sqlSettings = val self.Statistics._makeSQLMethods(prefix=db_pref) security.declareProtected(perm_manage, 'getSQLSettings') def getSQLSettings(self): """ get sql settings """ try: return self._sqlSettings except AttributeError: return {'database':'', 'port':'3306', 'username':'', 'socket':'', 'password':'', 'hostname':'', 'table_prefix':'iva'} def getCourseForID(self, REQUEST, course_id, curUser): """ return course instance or set current course id to 0 """ #if not hasattr(self.courses.aq_self, course_id): course = getattr(self.courses, str(course_id), '') if course == '' and int(course_id) != 0: curUser.jooksev_kursus = 0 return REQUEST.RESPONSE.redirect('organizer_index') return course security.declareProtected(perm_manage,'addCookieCrumbler') def addCookieCrumbler(self): """ xxx """ if hasattr(self.aq_self, 'login'): return cc = CookieCrumbler() cc.id = 'login' self._setObject('login', cc) #XXX: picture location!!! login_form = """
Please try again.
Forgot Password?
Name ">
Password
""" self.manage_addDTMLMethod('login_form','CookieCruymblers login form',login_form) getattr(self,'login_form').manage_permission('View',['Authenticated', 'Anonymous',], 1) cc = getattr(self, 'login') cc.auth_cookie = '__iva' cc.name_cookie = '__iva_name' cc.pw_cookie = '__iva_password' cc.persist_cookie = '__iva_persistent' return "ok" security.declarePublic('verifyUserLocation') def verifyUserLocation(self, userLocation): """ asd """ if userLocation not in ('Organizer','Workshops','Management','Bookshelf','Webtop', 'Scorm'): return 1 return 0 security.declarePublic('getRelativeURL') def getRelativeURL(self, content): """ Get the URL for an object, relative to the iva root. """ return '/'.join( self.getRelativeContentPath(content) ) security.declarePublic('getRelativeContentPath') def getRelativeContentPath(self, content): """ Get the path for an object, relative to the iva root. """ portal_path_length = len( self.fle_root().getPhysicalPath() ) content_path = content.getPhysicalPath() return content_path[portal_path_length:] #security.declareProtected(perm_view, 'getLangCode') security.declarePublic('getLangCode') def getLangCode(self, REQUEST, nr=0, curUser=None): """ return language code """ if curUser and not curUser.kasKeelBrauserist(): return curUser.get_language() lang = REQUEST.HTTP_ACCEPT_LANGUAGE # et,en;q=0.8,ru;q=0.5,en-us;q=0.3 existing_langs = self.get_languages() atmp = lang.split(',') # ['et', 'en;q=0.8', 'ru;q=0.5', 'en-us;q=0.3'] --> 'et' if len(atmp)>nr: a = atmp[nr] else: return 2 b = a.split(';')[0] c = b.split('-')[0] if c not in existing_langs: status = self.getLangCode(REQUEST, nr+1) if status == 2: return 'en' c = status return c security.declareProtected(perm_manage, 'setupSkins') def setupSkins(self): """ setup skins """ from Products.CMFCore.utils import manage_addTool add_tool = self.manage_addProduct['CMFCore'].manage_addTool add_tool('CMF Skins Tool', None) sk_tool = getattr(self, self.getSkinsFolderName()) manage_addFolder(sk_tool, 'default_custom', 'Customize pages here for default skin') paths = """ default_custom, iva_main, styles, images, courses, management, fle_users, organizer, webtop, js, iva_mail, iva_blog, qt, subgroups, tracker, Wiki, wordmaps, kupu, typesets, wap """ sk_tool.addSkinSelection('default', paths, make_default = 1) from Products.CMFCore.DirectoryView import addDirectoryViews addDirectoryViews(sk_tool, 'ui/skins/default', globals()) return "Done" security.declareProtected(perm_manage, 'addIndexes') def addIndexes(self): """ add missing ZCatalog indexes XXX: there is no link to this yet """ cmz = getattr(self.courses, 'courses_zcatalog') cmz.addIndex('getUniqId', 'FieldIndex') cmz.refreshCatalog(clear=1) return "Done" security.declarePrivate('indexBlogs') def indexBlogs(self, a, b): """ asd """ cat = getattr(self, 'blogs_zcatalog') a.default_catalog = 'blogs_zcatalog' cat.catalog_object(a) return a security.declareProtected(perm_manage, 'migrateBlogs') def migrateBlogs(self, REQUEST, RESPONSE): """ migrate blogs - attach a catalog, index etc XXX: there is no link to this yet 1. create zcatalog 'blogs_zcatalog' 2. create add default_catalog to all entries 3. catalog blogs. """ self.add_blogs_zcatalog() cat = getattr(self, 'blogs_zcatalog') path = '/'.join(self.getPhysicalPath()) cat.ZopeFindAndApply(self, search_sub=1, obj_expr='isEntry()==1', apply_func=self.indexBlogs, apply_path=path) return "Done" security.declarePrivate('addWebtopItem') def addWebtopItem(self, a, b): """ asd """ cat = getattr(self, 'catalog_webtop_items') cat.catalog_object(a) return a security.declareProtected(perm_manage, 'catalogWebtopItems') def catalogWebtopItems(self): """ catalog all webtops """ try: cat = getattr(self, 'catalog_webtop_items') cat.delIndex('get_content') except: pass cat = getattr(self, 'catalog_webtop_items') path = '/'.join(self.getPhysicalPath()) cat.ZopeFindAndApply(self, search_sub=1, obj_expr="default_catalog=='catalog_webtop_items' and meta_type in ['WebtopFile', 'WebtopFolder', 'WebtopItem', 'WebtopLink', 'WebtopMemo', 'WebtopProxyFile', 'Webtop', 'SubgroupManager', 'Subgroup', 'Portfolio', 'AssignmentProxy', 'GroupFolder']", apply_func=self.addWebtopItem, apply_path=path) return "Done" security.declareProtected(perm_manage, 'addCaches') def addCaches(self): """ migrate to version 1.0 """ self.images._delObject('HTTPCache') AcceleratedHTTPCacheManager.manage_addAcceleratedHTTPCacheManager(self, 'HTTPCache') http_cache = getattr(self, 'HTTPCache') http_cache.manage_editProps('', {'anonymous_only':0, 'interval':3600, 'notify_urls':''}) # add uniq id to users um = self.fle_users for x in um.get_users(): suffix = '_'+str(int(time.time())) uniq_id = um.generateId(prefix='user',suffix=suffix, rand_ceiling=99999999999) x.setUniqId(uniq_id) cat = getattr(self, 'catalog_webtop_items') cat.delIndex('get_content') return "Done" security.declareProtected(perm_manage, 'createQTImages') def createQTImages(self): """ create qtImages inside 'testid' folder """ # XXX: write me # 1. find all courses. # 2. get testid folder # 3. qti = QTImages() # 4. self._setObject(qti.id, qti) cm = self.courses from QTImages import QTImages for x in cm.objectValues('Course'): testid = getattr(x, 'testid') qti = QTImages() testid._setObject(qti.id, qti) self.migrateQTImages() return "Done" security.declareProtected(perm_manage, 'createTrackers') def createTrackers(self): """ create trackers - new in IVA 1.0 """ cm = self.courses for x in cm.objectValues('Course'): x.createTracker() return "Done" security.declareProtected(perm_manage, 'migrateQTImages') def migrateQTImages(self): """ migrate QT images """ import re for x in self.courses.objectValues('Course'): qtiimages = x.testid.qtimages j = 0 for q in x.testid.getQuizzes(): for z in q.ylesanded(): j = j + 1 if hasattr(z, 'pildid'): i = 0 for p in z.pildid: newid = 'Image'+str(j)+str(i) try: qtiimages.manage_addImage(newid, p, newid) except: qtiimages._delObject(newid) qtiimages.manage_addImage(newid, p, newid) subst = str(z.id+'/kysiPilt?pildinr='+str(i)) txt = z.kirjeldavTekst #txt = re.sub(subst, 'qtimages/'+newid, z.kirjeldavTekst.decode('utf-8')) txt = re.sub(z.id, 'qtimages', txt) txt = re.sub('kysiPilt', newid, txt) txt = re.sub('\?pildinr='+str(i), '', txt) z.kirjeldavTekst = txt i = i + 1 del z.pildid return "Done" security.declareProtected(perm_manage, 'migrateTo10') def migrateTo10(self): """ migrate IVA to version 1.0 """ self.delete_pt() self.createQTImages() self.addCaches() self.migrateBlogs() self.addIndexes() self.setupSkins() self.createTrackers() self.catalogWebtopItems() security.declareProtected(perm_manage, 'migrateTo11') def migrateTo11(self): """ migrate to IVA 1.1 """ self.migrateMailhost() self.migrateScheduler() return 0 security.declareProtected(perm_manage, 'migrateMailhost') def migrateMailhost(self): """ migrates mailhost """ mh = host = tit = '' port = 25 try: mh = self.MailHost tit = mh.title host = mh.smtp_host port = mh.smtp_port self._delObject('MailHost') except: pass from Products.SecureMailHost import SecureMailHost mailhost = SecureMailHost.SecureMailHost('MailHost', tit, host, port) self._setObject('MailHost', mailhost) return "Done - review MailHost settings" security.declareProtected(perm_manage, 'migrateScheduler') def migrateScheduler(self): """ add yourself to scheduler """ cp = self.Control_Panel cp._delObject('timerservice') return "Done" security.declareProtected(perm_manage, 'translate_wap') def translate_wap(self, totranslate, REQUEST): """ Give translation to WAP pages """ return translate(self, totranslate,target=self.giveLanguage(REQUEST)); Globals.InitializeClass(FLE) @adapter(IFLE, IObjectAddedEvent) def added(obj, event): """Add roles to the root level Fle folder and do other initialization tasks.""" try: obj.setupSkins() except: pass # Add images to images/ manage_addFolder(obj, 'images', 'Images') ims = getattr(obj, 'images') obj.reload_images() manage_addFolder(ims, 'courses_imgs', '') manage_addFolder(ims, 'users_imgs', '') try: AcceleratedHTTPCacheManager.manage_addAcceleratedHTTPCacheManager(obj, 'HTTPCache') except: pass http_cache = getattr(obj, 'HTTPCache') http_cache.manage_editProps('', {'anonymous_only':0, 'interval':3600, 'notify_urls':''}) stats = getattr(obj, 'Statistics', None) if stats is None: from Statistics import StatisticsManager stats = StatisticsManager() obj._setObject(stats.id, stats) if not hasattr(obj.aq_self, 'qtCatalog'): obj._setObject('qtCatalog', YlHoidla()) if hasattr(obj,'typesets'): # If the typesets directory already exists, then this # isn't the initial installation, but rather a rename # or a move operation. # Skip everything! return obj.manage_addProperty('Autoregister', 0, 'boolean') # add property for FLE version number obj.manage_addProperty('webtop_quota', 1, 'boolean') obj.manage_addProperty('webtop_quota_amount', obj._quota, 'string') obj.manage_addProperty('default_language', obj._default_lang, 'string') obj.manage_addProperty('IVA_VERSION', IVA_VERSION, 'string') obj.manage_addProperty('MFROM',obj.mfrom,'string') obj.manage_addProperty('def_passwd',int(obj.def_asswd),'boolean') obj.manage_addProperty('def_not_change',int(obj.def_ot_change),'boolean') obj.manage_addProperty('def_not_aff',int(obj.def_ot_aff),'boolean') tts_manager = TTSM('typesets', '') obj._setObject('typesets', tts_manager) tts_manager=tts_manager.__of__(obj) #from Downloader import Downloader #obj._setObject('download',Downloader()) manage_addFolder(obj, 'uploads','Wiki uploads') from common import fle_roles for role in fle_roles: obj._addRole(role) obj._addRole('Items') obj.manage_permission(perm_access, ('Manager','IVAAdmin','Member','Owner') ,0) obj.manage_permission(perm_view, ('Authenticated','Manager','IVAAdmin','Member','Owner') ,0) obj.manage_permission(perm_edit, ('Manager',), 0) obj.manage_permission(perm_manage, roles_admin, 0) obj.manage_permission(perm_add_lo, roles_admin, 0) try: obj.manage_permission('Zwiki: Add comments', roles_user+('Authenticated','Owner',), 0) obj.manage_permission('Zwiki: Add pages', ('Owner',), 0) obj.manage_permission('Zwiki: Add wikis', ('Owner',), 0) obj.manage_permission('Zwiki: Change page types', ('Owner',), 0) obj.manage_permission('Zwiki: Delete pages', ('Owner',), 0) obj.manage_permission('Zwiki: Edit pages', ('Owner',), 0) obj.manage_permission('Zwiki: Rename pages', ('Owner',), 0) obj.manage_permission('Zwiki: Reparent pages', ('Owner',), 0) except ValueError: pass obj.uploads.manage_permission('Add Documents, Images, and Files', roles_user+('Authenticated','Owner',), 0) um_obj = UserManager('fle_users', #'FLE User Manager') '') obj._setObject('fle_users', um_obj) # Create default knowledge type sets, whether importing # or not. tts_manager.load_default_sets() # Let's do courses last, since if we're importing, we # need to have the users already in place. cm_obj = CourseManager('courses') obj._setObject('courses', cm_obj) obj.addCookieCrumbler() from Products.MailHost.interfaces import IMailHost from interfaces import IStatistics, IUserManager, ICourseManager sm = obj.getSiteManager() sm.registerUtility(obj.Statistics, IStatistics) sm.registerUtility(obj, IFLE) sm.registerUtility(obj.MailHost, IMailHost) sm.registerUtility(obj.fle_users, IUserManager) sm.registerUtility(obj.courses, ICourseManager) # FIXME: input_checks (some checks done in FLE.__init__) def manage_addFLE( self, id='', title='', try_it = 0, shere='', smtp_host='', smtp_port=25, lang='en', quota=3000000, mfrom='iva@localhost',def_passwd=0, def_not_change=0,def_not_aff=0): """Create a FLE object. (Product Factory Method).""" if try_it: warnings = [] errors = [] if not CCAware: warnings.append('CMF not installed - CookieCrumbler not available') if not PIL_imported: warnings.append('PIL not installed - image manipulations disabled') if not PLACELESS: warnings.append('PlacelessTranslationService not installed - translation disabled') if not ZWIKI_imported: warnings.append('ZWiki not installed - some parts of IVA might even not work.') if not SQL_INSTALLED: warnings.append('ZMySQLDA not installed - statistics will be disabled.') if not id: errors.append('No id specified') if id: used = 0 if id in shere.objectIds(): used = 1 if used: errors.append('ID is already in use') if not used: from input_checks import is_valid_id valid = is_valid_id(id) if not valid: errors.append('ID is not valid - do not use any special symbols') return {'errors':errors, 'warnings':warnings} #def_passwd = REQUEST.get('def_passwd',0) #def_not_change = REQUEST.get('def_not_change',0) #def_not_aff = REQUEST.get('def_not_aff',0) fle = FLE( id, title, smtp_host, smtp_port, lang, quota, mfrom, def_passwd,def_not_change,def_not_aff) self._setObject(id, fle) return 1 #manage_addFLEForm = Globals.HTMLFile('ui/IVA_creation_form', globals()) manage_addFLEForm = PageTemplateFile('ui/IVA_creation_form.zpt', globals()) # EOF