# -*- 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 package player for IVA """ __version__ = "0.1" import Globals from Products.iva.WebtopItem import WebtopItem from Globals import Persistent import OFS,time from AccessControl import ClassSecurityInfo from Products.iva.common import perm_view import urllib2 from urllib import urlencode, quote from zope.component import getUtility from zope.interface import implements from Products.iva.interfaces import IStatistics from interfaces import ISCORMFile class SCORMFile(WebtopItem, OFS.SimpleItem.Item): """ SCORM package """ meta_type = 'SCORMFile' security = ClassSecurityInfo() implements(ISCORMFile) def __init__(self, parent, name, public='', private='', package_id=''): """ Construct object """ WebtopItem.__init__(self, parent, name) self.id = self.id+'_scormpackage' self._public_key = public self._private_key = private self._package_id = package_id def manage_afterAdd(self, item, container): WebtopItem.manage_afterAdd(self, item, container) security.declareProtected(perm_view, 'getPackageId') def getPackageId(self): return self._package_id def _call_remote(self, url, data): """ call caldoz """ p = urlencode(data) url = self.scorm_player.getPlayerLocation()+url opener = urllib2.urlopen(url, p) return [opener.read(), opener.headers.type] security.declareProtected(perm_view, 'getTOC') def getTOC(self): p = { 'session_id': self.REQUEST.SESSION.get('scorm_session_key')} return self._call_remote('/getTOC', p)[0] security.declareProtected(perm_view, 'getNavigation') def getNavigation(self): p = { 'session_id': self.REQUEST.SESSION.get('scorm_session_key')} return self._call_remote('/getNavigation', p)[0] def get_size(self): return 1 security.declareProtected(perm_view, 'getRedirectURL') def getRedirectURL(self, session_key): """ redirect to Caldoz """ return "javascript:window.location='"+self.scorm_player.getPlayerLocation()+"/getCookie?session_key="+session_key+"&came_from="+self.absolute_url()+"/@@scorm_index.html?userLocation=Scorm'" def locate(self, REQUEST, name): qname = name stack = REQUEST.get('TraversalRequestNameStack') scorm_key = self.REQUEST.SESSION.get('scorm_session_key', '') real = getattr(self, name, None) if not scorm_key and not real: return self if real is None: stack.reverse() url = '/'.join(stack) while stack: stack.pop() params = {} try: for x in REQUEST.form.keys(): params[x] = REQUEST.get(x) except AttributeError: pass pp = urlencode(params) special = ['getLMSValues', 'getPrevChapter', 'getNextChapter', 'getStartingPage', 'setLMSValues'] if qname in special or [ s for s in special if s in url ]: qname = self._package_id if name in special: url = name else: comm = [ x for x in special if x==qname ] if not comm: comm = [ s for s in special if s in url ] if comm: url = comm[0] qname = quote(qname) url = quote(url) req_url = self.scorm_player.getPlayerLocation()+'/'+qname+'/'+url if self._package_id not in req_url: req_url = self.scorm_player.getPlayerLocation()+'/'+self._package_id+'/'+qname+'/'+url req = urllib2.Request(req_url, pp, {'Cookie': 'session_key='+scorm_key} ) opener = urllib2.urlopen(req) ctype = opener.headers.typeheader base_url = opener.url.replace(self.scorm_player.getPlayerLocation(), self.absolute_url()) tf = TempFile('tempo', opener.read(), ctype, base_url) return tf return real Globals.InitializeClass(SCORMFile) class TempFile(Persistent): """ temporary file """ security = ClassSecurityInfo() security.declareObjectPublic() def __init__(self, id, content, type, base): self.id = id self._content = content self._content_type = type self._base_url = base def index_html(self, REQUEST): """ index """ REQUEST.RESPONSE.setHeader('Content-Type', self._content_type) if 'text/html' in self._content_type.lower(): import re base_re_search=re.compile('()',re.I).search ibase = base_re_search(self._content) if ibase is None: from ZPublisher.HTTPResponse import start_of_header_search from cgi import escape body = self._content match = start_of_header_search(body) if match is not None: index = match.start(0) + len(match.group(0)) ibase = base_re_search(body) if ibase is None: cnt = ('%s\n\n%s' % (body[:index], escape(self._base_url, 1), body[index:])) return cnt print "returning original content" return self._content print "SCORM: oki, BASE:", ibase.group() new_content = "%s%s%s" % ( self._content[:ibase.start(0)], '', self._content[ibase.end(0):]) return new_content return self._content def __call__(self): return self._content