# -*- coding: utf-8 # -*- Mode: Python; py-indent-offset: 4 -*- # $Id$ # # Copyright (c) 2006-2008, Vahur Rebas # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ Main module """ __version__ = "$Revision$"[11:-2] import Globals from Globals import Acquisition, Persistent from Acquisition import aq_base, aq_inner, aq_parent, Explicit from AccessControl import ClassSecurityInfo, getSecurityManager from OFS.Folder import Folder from Products.PageTemplates.PageTemplateFile import PageTemplateFile from zope.interface import implements import Package from Package import NotAPackage from Session import Session from utils import gen_key from interfaces import ICaldoz import logging LOG = logging.getLogger('Caldoz') class Caldoz(Folder, Persistent, Explicit): """ Caldoz main class """ meta_type = 'Caldoz' security = ClassSecurityInfo() security.declareObjectPublic() implements(ICaldoz) manage_options = Folder.manage_options # setup methods security.declarePrivate('manage_afterAdd') def manage_afterAdd(self, item, container): self.setupTempFolder() def setupTempFolder(self): """ setup temporary folder for sessions """ self.manage_addProduct['TemporaryFolder'].constructTemporaryFolder('sessions', 'Sessions') # general methods def caldoz_root(self): """ root """ return self def getRelativeURL(self, content): """ getthe URL for an object, relative to the root folder """ return '/'.join( self.getRelativeContentPath(content) ) def getRelativeContentPath(self, content): """ Get the path for an object, relative to the iva root. """ portal_path_length = len( self.caldoz_root().getPhysicalPath() ) content_path = content.getPhysicalPath() return content_path[portal_path_length:] # ... def checkPermission(self): """ check permission """ sm = getSecurityManager() return sm.checkPermission('Manager portal', self) security.declareProtected('Manage portal', 'managerHandler') def managerHandler(self, REQUEST=None, package_id=None, reloadButton=None, deleteButton=None): """ manager handler """ if reloadButton and package_id: pac = getattr(self, package_id) pac.manage_afterAdd(pac, self) if deleteButton and package_id: self._delObject(package_id) if REQUEST is not None: return REQUEST.RESPONSE.redirect('caldoz_manager.html') return "reloaded" security.declareProtected('Manage portal', 'controlzHandler') def controlzHandler(self, REQUEST=None, limit_upload=0, clientids='', controls_button=''): """ manager controls handler """ if controls_button: self._limit_upload = limit_upload self._known_clients = [ x.strip() for x in clientids.split('\n') ] if REQUEST is not None: return REQUEST.RESPONSE.redirect('caldoz_manager.html') return "saved" def _getLimitedToKnown(self): return getattr(self, '_limit_upload', 0) def _getKnownClients(self): return getattr(self, '_known_clients', []) security.declareProtected('Manage portal', 'getKnownClients') def getKnownClients(self): kc = self._getKnownClients() return '\n'.join(kc) security.declareProtected('Manage portal', 'getLimitedToKnown') def getLimitedToKnown(self): return getattr(self, '_limit_upload', 0) # methods related with package security.declareProtected('Manage portal', 'getPackages') def getPackages(self): return self.objectValues('CaldozPackage') security.declareProtected('View', '_get_packages') def _get_packages(self): return self.objectValues('CaldozPackage') security.declareProtected('Caldoz: Direct upload', 'addNewPackage_direct') def addNewPackage_direct(self, REQUEST, file): """ add new package. file is zipfile used by caldoz directly """ import zipfile import tempfile fname = tempfile.mkstemp()[1] f = open(fname, "w+b") f.write(file.read()) f.close() if not zipfile.is_zipfile(fname): raise 'Error: file is not a zip file' file.seek(0) pac = Package.Package(file, clientID="browser") self._setObject(pac.id, pac) import os os.unlink(fname) return REQUEST.RESPONSE.redirect(pac.id) security.declarePublic('addNewPackage') def addNewPackage(self, file=None, clientid=''): """ add new package, return credentials file is base64 encoded string can be called from remote clients """ if self._getLimitedToKnown(): if clientid not in self._getKnownClients(): return "3Upload restricted" import zipfile import tempfile import base64 error = 0 error_explain = 'Upload was successful' fname = tempfile.mkstemp()[1] LOG.info('fname:'+fname) f = open(fname, "w+b") f.write(file.read()) f.close() if not zipfile.is_zipfile(fname): error = 1 file.seek(0) pac = None if not error: LOG.info('will create package') pac = Package.Package(file, clientID=clientid) try: self._setObject(pac.id, pac) except NotAPackage: self._delObject(pac.id) pac = None error = 2 error_explain = 'Uploaded file is not a SCORM package' else: LOG.info('not creating package'+str(error)) import os os.unlink(fname) if error == 1: error_explain = 'Uploaded file was not a Zip file.' LOG.info(error) ntitle = '' pid = '' pubk = '' prik = '' if pac is not None: pid = pac.getId() pubk = pac._getPublicKey() prik = pac._getPrivateKey() ntitle = pac.caldoz_getMainTitles()[0][0] msg = """ %s %s %s %s %s %s """ % ( pid, str(error), error_explain, ntitle, pubk, prik ) return msg security.declarePublic('updatePackage') def updatePackage(self, file, clientid, private_key): """ update an existing package """ pac = None pacId = '' error = 1 error_explain = 'Invalid key' ntitle = '' for x in self._get_packages(): if x._getPrivateKey() == private_key: pac = x break if pac is not None: from transaction import get as get_transaction transaction = get_transaction() savepoint = transaction.savepoint() try: pac._updateZip(file) pac.manage_afterAdd(pac, self) transaction.commit() pacId = pac.getId() error = 0 error_explain = '' ntitle = pac.caldoz_getMainTitles()[0][0] except NotAPackage: savepoint.rollback() error = 2 error_explain = 'Uploaded file is not a SCORM package' msg = """ %s %s %s %s """ % ( pacId, str(error), error_explain, ntitle ) return msg def packageInfo(self, private_key=''): """ get a package info - titles, keys """ pac = None pacId = '' error = 2 error_explain = "Invalid key" ntitle = '' pubkey = '' prikey = '' for x in self._get_packages(): if x._getPrivateKey() == private_key: pac = x break if pac is not None: pacId = pac.getId() error = 0 error_explain = '' ntitle = pac.caldoz_getMainTitles()[0][0] pubkey = pac._getPublicKey() prikey = pac._getPrivateKey() msg = """ %s %s %s %s %s %s """ % ( pacId, str(error), error_explain, ntitle, pubkey, prikey ) return msg security.declarePublic('deletePackage') def deletePackage(self, private_key=''): """ delete a package """ p = None status = 2 statusText = "Invalid key" for x in self._get_packages(): if x._getPrivateKey() == private_key: p = x break if p is not None: self._delObject(p.caldoz_getId()) status = 0 statusText = "Deleted" return """ %s %s """ % ( status, statusText) def generateKeys(self, private_key=''): """ generate new access keys for a package """ p = None status = 2 statusText = "Invalid key" pub = '' priv = '' for x in self._get_packages(): if x._getPrivateKey() == private_key: p = x break if p is not None: status = 0 statusText = "OK" pub = gen_key('public') priv = gen_key('private') p._public_key = pub p._private_key = priv return """ %s %s %s %s """ % ( status, statusText, pub, priv) security.declarePublic('getTOC') def getTOC(self, session_id): """ getTOC """ sess = getattr(self.sessions, session_id, None) if sess is None: return "NO TOC" pid = sess.package_id p = getattr(self, pid, None) if p is not None and (p._getPublicKey() == sess.access_key or p._getPrivateKey() == sess.access_key): return p.getTOC() return "" security.declarePublic('getNavigation') def getNavigation(self, session_id): """ get navigation """ sess = getattr(self.sessions, session_id, None) if sess is None: return "NO NAVIGATION" pid = sess.package_id p = getattr(self, pid, None) if p is None: return "Cannot find navigation" if p._getPublicKey() != sess.access_key and p._getPrivateKey() != sess.access_key: return "" #Invalid access key" msg = """""" msg += """""" msg += """""" msg += """""" return msg security.declarePublic('getCookie') def getCookie(self, REQUEST, session_key, came_from): """ get cookie """ REQUEST.RESPONSE.setCookie('session_key', session_key, expires='Wed, 19 Feb 2020 14:00:00 GMT') return REQUEST.RESPONSE.redirect(came_from) security.declareProtected('Manage portal', 'manager_login') def manager_login(self, REQUEST): """ manager logs in """ uname = str(getSecurityManager().getUser()) sess_id = gen_key('session') s = Session(sess_id, None, None, uname) if self.checkPermission(): s._setManager(True) self.sessions._setObject(s.id, s) return REQUEST.RESPONSE.redirect('getCookie?session_key='+sess_id+'&came_from='+self.absolute_url()+'/caldoz_manager.html') security.declarePublic('') def enterPackage(self, REQUEST, secret_key=None): """ enter package """ if not secret_key or secret_key is None: return sid = self.startSession(None, secret_key) return REQUEST.RESPONSE.redirect('getCookie?session_key='+sid+'&came_from=redirectToPackage') security.declarePublic('initialize_session') def startSession(self, package_id=None, access_key=None, uname='Anonymous User'): """ initialize session. If someone knows the key, go ahead """ p = None pid = package_id if pid is not None: p = getattr(self, package_id, None) else: for x in self._get_packages(): if x._getPrivateKey() == access_key \ or x._getPublicKey() == access_key: p = x pid = x.getId() break session_id = None if p is not None: if p._getPublicKey() == access_key or p._getPrivateKey() == access_key: session_id = gen_key('session') s = Session(session_id, pid, access_key, uname) self.sessions._setObject(s.id, s) return session_id security.declarePublic('redirectToPackage') def redirectToPackage(self, REQUEST): """ redirect to package """ sess_key = REQUEST.get('session_key', None) if sess_key is None: return REQUEST.RESPONSE.redirect(self.absolute_url()) sess = getattr(self.sessions, sess_key, None) if sess is None: return REQUEST.RESPONSE.redirect(self.absolute_url()) return REQUEST.RESPONSE.redirect(self.caldoz_root().absolute_url()+'/'+sess.package_id) Globals.InitializeClass(Caldoz) def manage_addCaldoz(self, REQUEST, id): """ instantiate Caldoz """ caldoz = Caldoz(id) self._setObject(id, caldoz) if REQUEST: return self.manage_main(self, REQUEST) manage_addCaldozForm = PageTemplateFile('skins/addCaldozForm.pt', globals()) # EOF