# -*- 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>(.*?)%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>(.*?)%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>(.*?)%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)