# -*- coding: utf-8 # $Id$ # # Copyright 2006 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 """ SCORM tool for IVA """ __version__ = "$Revision$"[11:-2] import Globals from Globals import Persistent from OFS import Folder from AccessControl import ClassSecurityInfo, getSecurityManager from zope.component import getUtility from Products.iva.interfaces import IUserManager from Products.iva.Cruft import Cruft from Products.iva.common import translate, perm_edit, perm_view, perm_manage, mkTime import time import urllib2 from urllib import urlencode import re class SCORMTool(Folder.Folder, Persistent, Cruft): """ SCORM Tool """ meta_type = 'SCORMTool' security = ClassSecurityInfo() security.declareObjectPublic() id = 'scorm_player' def isVisible(self): """ boolean - visible to users or not... """ if not hasattr(self, 'is_visible'): self.is_visible = False return self.is_visible security.declareProtected(perm_manage, 'setVisible') def setVisible(self, val): """ set visibility """ self.is_visible = int(val) def getPlayerLocation(self): """ get player location """ try: return self._player_location except AttributeError: return "" def _getPlayerIdentification(self): """ get player identification string """ try: return self._scorm_player_identification except AttributeError: return "" security.declareProtected(perm_manage, 'setPlayerLocation') def setPlayerLocation(self, loc): """ set player location """ self._player_location = loc security.declareProtected(perm_manage, 'setPlayerIdentification') def setPlayerIdentification(self, val): """ set player identification string """ self._scorm_player_identification = val def _add_helper(self, context, options, uname): from SCORMFile import SCORMFile sf = SCORMFile(context, options['name'], options['public'], options['private'], options['id']) context._setObject(sf.id, sf) # store user = self.fle_users.get_user_info(uname) new_key = gen_key() dd = { 'id': options['id'], 'name': options['name'], 'public': options['public'], 'private': options['private'], 'url': self.getRelativeURL(getattr(context, sf.id)) } #del user.scorm_plist try: while user.scorm_plist.has_key(new_key): new_key = gen_key() user.scorm_plist[new_key] = dd except AttributeError: from ZODB.PersistentMapping import PersistentMapping user.scorm_plist = PersistentMapping({new_key: dd}) return getattr(context, sf.id) def _delete_helper(self, info, iid): """ delete helper, removes a package from Caldoz server """ params = {'private_key': info.get('private')} p = urlencode(params) url = self.getPlayerLocation()+'/deletePackage' opener = urllib2.urlopen(url, p) resp = opener.read() res = re.search('(.*?)', resp).group(1) uname = str(getSecurityManager().getUser()) user = self.fle_users.get_user_info(uname) if int(res) == 0: cat = self.catalog_webtop_items q = {'meta_type': ('SCORMFile',), 'get_author': uname} sfiles = cat(q) for f in sfiles: obj = f.getObject() if obj.getPackageId() == info.get('id'): par = obj.aq_parent par._delObject(obj.getId()) user.scorm_plist.pop(iid) user.scorm_plist._p_changed = True return "Deleted!" return "Failed. Could not delete" security.declareProtected(perm_view, 'updateExisting') def updateExisting(self, context, REQUEST): """ update existing package """ if not self.isVisible(): return 'Critical error' req = REQUEST file = req.get('updatedfile') msg = 'Critical error' filename = file.filename.split('\\')[-1] filename = filename.split('/')[-1] content_type = file.headers.get('Content-Type') res = '' if 'zip' not in content_type.lower(): return 'File is not a Zip-file.' from http import post_multipart uname = str(getSecurityManager().getUser()) um = getUtility(IUserManager) user = um.get_user_info(uname) pl = None try: pl = user.scorm_plist except AttributeError: pl = None if pl is None: return 'Error' pack = pl.get(req.get('existing_package')) response = post_multipart( self.getPlayerLocation()+'/updatePackage', '', (('clientid', self._getPlayerIdentification()), ('private_key', pack.get('private'))), (('file', filename, file.read()),) ) res = response.read() mss = {} for x in ('id', 'status', 'name', 'statusText' ): try: mss[x] = re.search('<%s>(.*?)' % (x, x), res).groups()[0] except IndexError: mss[x] = None except AttributeError: mss[x] = None if mss['status'] == '0': user.scorm_plist[req.get('existing_package')]['name'] = mss['name'] user.scorm_plist._p_changed = True msg = 'Success!' # TODO: handle name switch elif mss['status'] == '1': msg = 'Invalid key' elif mss['status'] == '2': msg = 'Uploaded file is not a SCORM package.' return msg security.declareProtected(perm_view, 'uploadPackage') def uploadPackage(self, context, REQUEST): """ upload package """ if not self.isVisible(): return 'Critical error' req = REQUEST file = req.get('file') msg = 'Critical error' filename = file.filename.split('\\')[-1] filename = filename.split('/')[-1] content_type = file.headers.get('Content-Type') res = '' if 'zip' in content_type.lower(): from http import post_multipart response = post_multipart( self.getPlayerLocation()+'/addNewPackage', '', (('clientid', self._getPlayerIdentification()),), (('file', filename, file.read()),) ) res = response.read() else: msg = 'File is not a Zip-file.' mss = {} for x in ('id', 'status', 'name', 'statusText', 'public', 'private'): try: mss[x] = re.search('<%s>(.*?)' % (x, x), res).groups()[0] except IndexError: mss[x] = None except AttributeError: mss[x] = None if mss['status'] == '0': msg = 'Success!' # +mss['statusText'] uname = str(REQUEST.AUTHENTICATED_USER) self._add_helper(context, mss, uname) if mss['status'] == '1': msg = 'File is not a Zip-file.' if mss['status'] == '2': msg = 'Uploaded file is not a SCORM package.' if mss['status'] == '3': msg = 'Upload limited. Cannot add new files.' return msg security.declareProtected(perm_view, 'getExistingPackages') def getExistingPackages(self, REQUEST): """ return a list of existing scorm packages """ uname = str(getSecurityManager().getUser()) um = getUtility(IUserManager) user = um.get_user_info(uname) pl = None try: pl = user.scorm_plist except AttributeError: pl = None if pl is None: return [] res = [] seen_privs = [] for x in pl.keys(): if pl[x].get('private') in seen_privs: continue res.append([pl[x].get('name'), x, pl[x]]) seen_privs.append(pl[x].get('private')) return res def addExisting(self, context, req): """ add existing package """ uname = str(getSecurityManager().getUser()) um = getUtility(IUserManager) user = um.get_user_info(uname) pack = user.scorm_plist.get(req.get('existing_package')) self._add_helper(context, pack, uname) return "Success!" def deleteExisting(self, context, req): """ delete existing package, permanently """ uname = str(getSecurityManager().getUser()) um = getUtility(IUserManager) user = um.get_user_info(uname) pack = user.scorm_plist.get(req.get('existing_package')) msg = self._delete_helper(pack, req.get('existing_package')) return msg def probeAccess(self, context, REQUEST, k): """ probe for access """ params = {'private_key': k} p = urlencode(params) url = self.getPlayerLocation()+'/packageInfo' opener = urllib2.urlopen(url, p) res = opener.read() status = re.search('(.*?)', res).group(1) msg = 'Invalid key' if status == '0': mss = {} for x in ('id', 'status', 'name', 'statusText', 'public', 'private'): try: mss[x] = re.search('<%s>(.*?)' % (x, x), res).groups()[0] except IndexError: mss[x] = None except AttributeError: mss[x] = None msg = 'Success!' uname = str(REQUEST.AUTHENTICATED_USER) self._add_helper(context, mss, uname) return msg def gen_key(): from md5 import md5 import time return md5(str(time.time())).hexdigest() Globals.InitializeClass(SCORMTool)