# -*- 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 Cruft, which is used as a placeholder for miscellaneous utility functions that many objects need.""" __version__ = "$Revision$"[11:-2] from AccessControl import ClassSecurityInfo from urllib import quote from common import perm_view, perm_edit, perm_manage, perm_add_lo, translate import re import common import time from common import get_local_roles import string from DateTime import DateTime import calendar calendar.setfirstweekday(0) from Errors import FleError from Features import _FEATURES class Cruft: """Class containing miscellaneous methods that are historical baggage, but possible be gotten rid of, or at least implemented differently or somewhere else.""" security = ClassSecurityInfo() security.declarePublic('find_URL_of_fle_root') def find_URL_of_fle_root(self, REQUEST): """Return URL of our FLE installation.""" import FLE from string import rfind url = REQUEST.URL1 obj = self while not isinstance(obj, FLE.FLE): obj = obj.parent() url = url[:rfind(url,'/')] return url def find_URL_of_user_info(self, REQUEST): """Return URL of UserInfo.""" import UserInfo from string import rfind url = REQUEST.URL1 obj = self while not isinstance(obj, UserInfo.UserInfo): obj = obj.parent() url = url[:rfind(url,'/')] return url security.declarePublic('find_URL_of_webtop') def find_URL_of_webtop(self, REQUEST): """Return URL of Webtop.""" import Webtop from string import rfind url = REQUEST.URL1 obj = self while not isinstance(obj, Webtop.Webtop): obj = obj.parent() url = url[:rfind(url,'/')] return url security.declarePublic('find_URL_of_group_folder') def find_URL_of_group_folder(self, REQUEST): """Return URL of toplevel group folder or group folder proxy.""" import GroupFolder import GroupFolderProxy from string import rfind url = REQUEST.URL1 obj = self while 1: if isinstance(obj, GroupFolderProxy.GroupFolderProxy): return url if isinstance(obj, GroupFolder.GroupFolder): return url obj = obj.parent() url = url[:rfind(url,'/')] return url security.declarePublic('find_URL_of_thread_start_node') def find_URL_of_thread_start_node(self, REQUEST): """Return URL of starting note.""" import CourseContext from string import rfind url = REQUEST.URL1 obj = self while not isinstance(obj.parent(), CourseContext.CourseContext): obj = obj.parent() url = url[:rfind(url,'/')] return url security.declarePublic('find_URL_of_course') def find_URL_of_course(self, REQUEST): """Return URL of starting note.""" obj = self while not obj.meta_type == 'Course': obj = obj.parent() return obj.absolute_url() security.declarePublic('find_URL_of_course_context') def find_URL_of_course_context(self, REQUEST): """Return URL of starting note.""" import CourseContext from string import rfind url = REQUEST.URL1 obj = self while not isinstance(obj, CourseContext.CourseContext): obj = obj.parent() url = url[:rfind(url,'/')] return url security.declarePublic('is_student') def is_student(self, REQUEST,nr=None, uname=''): """ is give user is student in given course """ splitter = '/' if splitter not in REQUEST.PATH_TRANSLATED: splitter = '\\' if nr is None: nr = self.jooksva_kursuse_nr(REQUEST,uname) ic = string.rfind(REQUEST.PATH_TRANSLATED, 'fle_users') url = REQUEST.PATH_TRANSLATED if ic == -1: nr = self.fle_root().courses.get_course_id_from_req(REQUEST) else: i = ic plst = filter(lambda x:x, string.split(url[i:], splitter)) nr = plst[3][1:] if not hasattr(self.fle_root().courses, str(nr)): return 0 checkname = str(REQUEST.AUTHENTICATED_USER) if 'Student' in get_local_roles(getattr(self.fle_root().courses, nr),checkname): return 1 try: fm = getattr(self.fle_root().fle_users, checkname) if fm.has_any_role(('IVAAdmin','Manager')): return 1 except: return 0 return 0 security.declarePublic('kas_opetaja') def kas_opetaja(self,REQUEST,nr=None,uname=''): """ If user is teacher. Additional role checks """ if nr is None: nr = self.jooksva_kursuse_nr(REQUEST,uname) if not hasattr(self.fle_root().courses, str(nr)): return 0 if uname: pass #checkname = uname else: pass checkname = str(REQUEST.AUTHENTICATED_USER) if checkname in getattr(self.fle_root().courses, nr).get_teachers(): return 1 #try: #XXX: Should we put try except here? if 1==1: fm = getattr(self.fle_root().fle_users, checkname) #XXX: this sucks? if fm.has_any_role(('IVAAdmin','Manager')): return 1 return 0 security.declarePublic('jooksva_kursuse_nimi') def jooksva_kursuse_nimi(self,REQUEST,uname=''): """ jooksva kursuse nimi """ nr = self.jooksva_kursuse_nr(REQUEST,uname) try: return str(getattr(self.fle_root().courses, nr).get_name()) except: return translate(self,"course not selected", target=self.giveLanguage(REQUEST)) security.declarePublic('jooksva_kursuse_nr') def jooksva_kursuse_nr(self,REQUEST,uname=''): """ jooksva kursuse number """; try: if uname: return str(getattr(self.fle_root().fle_users, uname).get_jooksev_kursus()) else: return str(getattr(self.fle_root().fle_users, self.get_current_user(REQUEST)).get_jooksev_kursus()) except: return 0 security.declarePublic('get_current_user') def get_current_user(self, REQUEST): """Extract current user's name from the REQUEST object.""" return str(REQUEST.AUTHENTICATED_USER) security.declarePublic('urlquote') def urlquote(self, text): """urlquote given text.""" return quote(text) def get_url_to_object(self,obj): # Make a list of parents without the Application object # (from obj to FLE) return obj.absolute_url()+'/' #objs = obj.aq_inner.aq_chain[:-1] #objs.reverse() #path='/'.join([x.getId() for x in objs])+'/' #return path def get_object_of_url(self,url,base,remove_last=1): #XXX: broken for VirtualHostMonster! path=url.split('/') if remove_last: path.pop() # remove last entry path.reverse() if path[-1]=='http:': # remove protocol path.pop() path.pop() path.pop() # remove first (root) entry obj = base.fle_root() #obj = base.getPhysicalRoot() try: while path: oname=path.pop() obj=getattr(obj,oname).__of__(obj) return obj except: #raise 'Internal link error, object not found',str(obj)+' - '+oname return None def kasutajaURList(self, REQUEST): "Kasutajanimi" nimi=self.kasutajaNimi(REQUEST) if nimi=="": return nimi if nimi==str(REQUEST.AUTHENTICATED_USER): return "" return "> " + ""+nimi+"" def algusURList(self, REQUEST, osa): "URL soovitud loiguni" x=REQUEST.URL0 if x.find(osa)==-1: return "" return x[:x.find(osa)+len(osa)] def kasLopeb(self, tekst, otsitav): "jah/ei" # return tekst+" ja " + otsitav return tekst.endswith(otsitav) def myOwnWebtop(self, REQUEST): "jah/ei" return self.kasutajaNimi(REQUEST)==str(REQUEST.AUTHENTICATED_USER) def kasutajaNimi(self, REQUEST): "nimi" aadress=REQUEST.URL0 nr=aadress.find('fle_users') if nr==-1: return "" ots=aadress.find('/', nr+10) nimi=aadress[nr+10:ots] nimi = re.sub('%20', ' ',nimi) return nimi def ajaMuutmisElemendid(self, elemendinimi, aeg=-1): "Valikute kogum" import YlTest from YlTest import LahendusLuba from types import StringType abi=LahendusLuba() if type(aeg)==StringType: aeg=float(aeg) if aeg==-1:aeg=time.time() m=time.localtime(aeg) tulemus=abi.looValik(elemendinimi+"Aasta", m[0]-5, m[0]+10, m[0]) tulemus=tulemus+"-"+\ abi.looValik(elemendinimi+"Kuu", 1, 12, m[1]) tulemus=tulemus+"-"+\ abi.looValik(elemendinimi+"Paev", 1, 31, m[2]) tulemus=tulemus+" "+\ abi.looValik(elemendinimi+"Tund", 0, 23, m[3]) tulemus=tulemus+":"+\ abi.looValik(elemendinimi+"Minut", 0, 59, m[4], samm=5) return tulemus def set_undefined_page(self, message, REQUEST): """Set REQUEST.RESPONSE.redirect, so that we go to undefined page and give an explanation.""" message = common.quote_html_hack(message) REQUEST.RESPONSE.redirect("undefined_page?explanation=%s" % message) security.declarePublic('to_str_list') # Using eval would be simpler and more general, but # we want to be paranoid. def to_str_list(self, s): """Reverse str representation of list of strings back to list.""" return [x.strip() for x in s[1:-1].replace("'", "").split(',')] def kasutajaasukoht(self, REQUEST,url=''): "Kasutaja asukoht" if url: x = url else: x = REQUEST.URL0 if x.find('manage')>0: return "Management" if x.find('tracker_show')>0: return "Bookshelf" if x.find('tracker')>0: return "Management" if x.find('WelCome')>0: return "Bookshelf" #Course ZWiki if x.find('assignmentGrading')>0: return "Webtop" if x.find('createMail')>0 or x.find('edit_user_form')>0 or x.find('show_user_info')>0: return 'Organizer' if x.find('kalendriAasta')>0 or x.find('organizer')>0 or x.find('logout')>0: return 'Organizer' if x.find('course_info_user')>0: return "Webtop" if x.find('course_index')>0 or x.find('course_info')>0: return 'Bookshelf' if x.find('tootubade_leht')>0 or x.find('workshop_')>0: return "Workshops" if x.find('/courses/')>0: if x.find('/testihaldus')>0 or x.find('/courses/index_html')>0 or self.kas_haldus(REQUEST,x): return "Management" if not x.find('/gf/')>0 and x.find('/testid/')>0: return "Management" if x.find('import_form_handler2')>0: return "Management" if not x.find('/gf/')>0: return "Workshops" if x.find('/fle_users/')>0 and x.find('/webtop/')>0: return "Webtop" if self.kas_haldus(REQUEST, x) or x.find('ootajateLoetelu')>0: return 'Management' else: return 'Bookshelf' def sisegrupiNimi(self, REQUEST): "URList loetud grupi nimi" #XXX: remove x=REQUEST.URL0 if x.find('/subgroups/')>0: algus=x.find('/subgroups/') ots=x.find('/', algus+11) if ots==-1: tulemus=x[algus+11:] else: tulemus=x[algus+11:ots] if tulemus == 'wt_index_html': return "listing" return tulemus else: return "" security.declarePublic('kas_haldus') def kas_haldus(self, REQUEST, veebiurl): "kas sobib halduseks" if re.match(".*/courses/[0-9]+/syndmused", veebiurl): if self.kas_opetaja(self, REQUEST): return 1 else: return 0 laused=( ".*haldusleht", ".*testihaldus", ".*muuda_vorm", ".*kysimuse_vorm", ".*add_course_form", ".*sisegrupihaldus", ".*courses/index_html", ".*ylesandedMuutmisTabelina", ".*ylesanneteTyypideLoetelu", ".*pealkirjaMuutmisVormHTML", ".*muutmisVorm", ".*lubadeViited", ".*koigiLuba", ".*isikuLubadeLisamisVorm", ".*grupiLubadeLisamisVorm", ".*/filtreerimisvorm2", ".*/kasutajateTulemused", ".*/typesets", ".*/lahendusteStatistika", ".*/kodutood.*", ".*/manage_.*", ".*qtCatalog.*", #".*", ) leitud=0 x=veebiurl for lause in laused: if re.match(lause, x): leitud=1 return leitud security.declarePublic('kas_kasutaja_haldus') def kas_kasutaja_haldus(self, veebiurl): "kas sobib halduseks" laused=( ".*kasutajate_haldamise_vorm", ".*kasutajateLisamisFailiVorm", ".*kasutajaLehelt1", ".*kasutajadFailist2", ".*kasutajadFailist1", ".*erialadeHalduseVorm", ".*/kasutajaotsing", ".*/kasutajateKustutus.*", #".*", ) leitud=0 x=veebiurl for lause in laused: if re.match(lause, x): leitud=1 return leitud security.declareProtected(perm_view, 'search_users') #XXX: is tthis right? def search_users(self, first_name='', last_name='', uname='', organization='', exclude=[], sort_on='get_last_name'): """ search users from zcatalog. exclude - excludes usernames, must be a list of username """ if organization == '-1': organization='' elif not organization: organization='' else: organization = self.fle_users.getAffiliation(int(organization)) query = { 'get_first_name':first_name, 'get_last_name':last_name, 'get_uname':uname, 'get_organization':organization, } results = self.fle_users.userinfo_zcatalog(query) tmp = [] if exclude: for x in results: if x.get_uname in exclude: continue tmp.append(x) else: tmp = results return tmp def zwiki_export(self,REQUEST,level,wiki_id): """ zwiki manage form handler """ from ImportExportIMS import Kirjutus from ImportExportIMS import kirjutaYldM import tempfile, os failinimi = tempfile.mktemp() if not level: level=99999 # number = self.get_course_id_from_req(REQUEST) number = 0 # nr = self.get_id() # try: # number = int(nr) # except: # number = int(nr[1:]) yld = kirjutaYldM() yld.kirjutaYldmanifest(number,'WIKI',base=str(number)+'/') yld.lisaFaili(failinimi) k = Kirjutus(self.fle_root(), number) k.looKursuseFail(0) wikikoht='' try: wikikoht = getattr(self,wiki_id) except: pass if wikikoht: k.kirjutaWiki(wikikoht,'ZWiki',wikikoht.aq_inner.get_name(),wikikoht.wikiKaustEsimeneLeht(),palju=level) # else: # k.kirjutaKasutajaWiki((self.get_user_info(str(REQUEST.AUTHENTICATED_USER)),)) k.pakiKursusFaili(failinimi) file = open(failinimi,"rb") export_data=file.read() file.close() os.remove(failinimi) REQUEST.RESPONSE.setHeader('Content-disposition','attachment; filename=zwikiexport.zip') REQUEST.RESPONSE.setHeader('content-type','application/zip') return export_data security.declareProtected(perm_view, 'saadaEmail') def saadaEmail(self,tomail,subject,message,saatja=''): """ proovime saata kirja """ p_saatja = '' if saatja: p_saatja = saatja if hasattr(self,'MFROM') and not p_saatja: p_saatja = self.MFROM if not p_saatja: return 0 try: mailhost = self.MailHost #message = "Content-Type:text/plain; charset=utf-8\n\n\n"+message #message = message+"\n\n\nThis message was sent to you in IVA and it was forwared to your email as you requested." #mailhost.secureSend(message,tomail,p_saatja,subject,encode='quoted-printable') mailhost.secureSend(message,tomail,p_saatja,subject,charset='utf-8') return 1 except: return 0 def leivaPuru(self,REQUEST): """ leivapuru """ #XXX:maybe we don't need this! if REQUEST.URL0.find('kirjad')>0: return REQUEST['L_ic_mailbox'] if self.kasLopeb(REQUEST.URL1, 'webtop/c'+str(self.jooksva_kursuse_nr(self, REQUEST))): return 'portfolio' else: return ""+'portfolio'+"" return "kala" def numberToText(self, REQUEST, arv): "Asendab punkti komaga, kui see vajalik" tekst=str(arv) eraldaja=translate(self, "decimal_separator", target=self.giveLanguage(REQUEST)) tekst=tekst.replace(".", eraldaja) return tekst security.declarePublic('giveLanguage') def giveLanguage(self, REQUEST): """ gives user language """ prev_lang = REQUEST.HTTP_ACCEPT_LANGUAGE isAnon = 0 try: if getattr(self.fle_root().fle_users, str(REQUEST.AUTHENTICATED_USER)).kasKeelBrauserist(): language = prev_lang else: language = getattr(self.fle_root().fle_users, str(REQUEST.AUTHENTICATED_USER)).get_language() except AttributeError: language = prev_lang isAnon = 1 #XXX: let's see if this works.. if language == 'et_ee': language = 'et' if language not in self.get_languages() and not isAnon: language = prev_lang language = self.default_language return language def firstAndLast(self,uname='',req=None): """ Give object author's first and last name """ abc = '' if not uname and not req: abc = self.getOwnerTuple()[1] if not uname and not abc and req: abc = str(req.AUTHENTICATED_USER) elif not uname and not abc and not req: abc = uname elif uname: abc = uname try: ui = self.fle_users.get_user_info(str(abc)) if ui and ui.get_first_name()!='' and ui.get_last_name()!='': nimi = ui.get_first_name()+" "+ui.get_last_name() else: nimi = abc except FleError: nimi = uname return nimi def lastAndFirst(self,uname='',req=None): """ Give object author's first and last name """ abc = '' if not uname and not req: abc = self.getOwnerTuple()[1] if not uname and not abc and req: abc = req.AUTHENTICATED_USER elif uname and not abc and not req: abc = uname try: ui = self.fle_users.get_user_info(str(abc)) if ui.get_first_name()=='' and ui.get_last_name()=='': nimi = abc else: nimi = ui.get_last_name()+", "+ui.get_first_name() except FleError: nimi = uname return nimi def is_courseContext(self): return 0 def getCalendar(self): """ return closest calendar """ return getattr(self, 'syndmused', None) def batch_previous(self, batch): """ generate links to next and previous pages """ result = [] while batch.previous: batch = batch.previous result.append(batch.start-1) result.reverse() return result def batch_next(self, batch): """ return an array of next batch staring points """ result = [] while batch.next: batch = batch.next result.append(batch.start-1) return result security.declareProtected(perm_manage, 'migratePersonalEvents') def migratePersonalEvents(self): """ from 0.7 to 0.8 disables creation of personal event method will go through all user's personal 'syndmused' folder and remove 'Add FLE LO' permission from everybody 'Add FLE LO' permission will be given to 'User' and 'Owner' on 'subgroups' folder. """ a = self.courses.courses_zcatalog.addColumn('getLogoThumbnailURL') for c in self.courses.get_courses(): g = c.getObject() subgroup = getattr(g.aq_inner, 'subgroups', None) if subgroup is None: continue subgroup.manage_permission('Add FLE LO', ('Owner', 'User'), 1) for u in self.fle_users.get_users(): s = getattr(u.aq_inner, 'syndmused', None) if s is None: continue s.manage_permission('Add FLE LO', (), 0) return "Removed 'Add FLE LO' permission from users. Added 'Add FLE LO' permission on subgroups. Added thumbnail url metadata to course_zcatalog." security.declareProtected(perm_manage, 'migrateTo072') def migrateTo072(self): """ migrates IVA to version 0.7.2 """ um = self.fle_users umz = um.userinfo_zcatalog umz.delIndex('get_organization') umz.addIndex('get_organization', 'FieldIndex') return "done" security.declareProtected(perm_view, 'format_date') def format_date(self, REQUEST, timestamp): """ format timestamp """ return time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)), time.localtime(timestamp)) security.declareProtected(perm_manage, 'getFeatures') def getFeatures(self, installed=1, not_installed=0): """ get all (not)installed features """ if not hasattr(self, 'features_table'): self.features_table = {} self._p_changed = True res = [] for x in _FEATURES.keys(): if installed: if not self.features_table.has_key(x): continue if self.features_table[x]['installed']: res.append(x) if not_installed: if not self.features_table.has_key(x): res.append(x) continue if not self.features_table[x]['installed']: res.append(x) return res def getFeatureDescription(self, feature, spec): """ return feature description """ return _FEATURES[feature][spec] security.declareProtected(perm_manage, 'enableFeature') def enableFeature(self, REQUEST=None, feature='_x'): """ enable module - usually it means setting up skins and possibly some objects """ if not _FEATURES.has_key(feature): raise 'Not available' f = _FEATURES.get(feature) if f.has_key('skins_folder'): #from Products.CMFCore import getToolByName from common import install_subskin #skins_tool = getToolByName(self, 'portal_skins') from StringIO import StringIO out = StringIO() install_subskin(self, out, globals(), f['skins_folder']) if f.has_key('install_method'): if callable(f.get('install_method')): f.get('install_method')(self) if not hasattr(self, 'features_table'): self.features_table = {} if not self.features_table.has_key(feature): self.features_table[feature] = {} self.features_table[feature]['installed'] = True self._p_changed = True if REQUEST: return REQUEST.RESPONSE.redirect('manage_iva_setup') return 0 security.declareProtected(perm_manage, 'disableFeature') def disableFeature(self, REQUEST=None, feature='_x'): """ disable feature XXX: should add support for uninstall method? """ if not _FEATURES.has_key(feature): raise 'Not available' from Products.CMFCore.utils import getToolByName f = _FEATURES.get(feature) skins_tool = getToolByName(self, 'portal_skins') skins = skins_tool.getSkinSelections() for skin in skins: path = skins_tool.getSkinPath(skin) path = [p.strip() for p in path.split(',') if p] while f['skins_folder'] in path: path.remove(f['skins_folder']) skins_tool.addSkinSelection(skin, ','.join(path)) self.features_table[feature]['installed'] = False self._p_changed = True if REQUEST: return REQUEST.RESPONSE.redirect('manage_iva_setup') return 0 def isFeatureEnabled(self, feature): """ is feature enabled """ try: return self.features_table[feature]['installed'] except AttributeError: return False except KeyError: return False def isFeatureVisible(self, feature): """ should feature be visible to users or not """ if not self.isFeatureEnabled(feature): return False return getattr(self, _FEATURES.get(feature)['toolid']).isVisible() security.declareProtected(perm_manage, 'featureManagement') def featureManagement(self, REQUEST, feature): """ return feature management page """ if not _FEATURES.has_key(feature): raise 'Not available' return getattr(self, _FEATURES[feature]['management'])(userLocation='Management') def DictPrinter(self, d): """ generated html from dictionary """ r = '