Beispiel #1
0
 def handleSavePackage(self, client, filename=None, onDone=None):
     """
     Save the current package
     'filename' is the filename to save the package to
     'onDone' will be evaled after saving instead or redirecting
     to the new location (in cases of package name changes).
     (This is used where the user goes file|open when their 
     package is changed and needs saving)
     """
     filename = Path(filename)
     saveDir  = filename.dirname()
     if saveDir and not saveDir.exists():
         client.alert(_(u'Cannot access directory named ') +
                      unicode(saveDir) +
                      _(u'. Please use ASCII names.'))
         return
     oldName = self.package.name
     if not filename:
         filename = self.package.filename
         assert (filename, 
                 ('Somehow save was called without a filename '
                  'on a package that has no default filename.'))
     if not filename.lower().endswith('.elp'):
         filename += '.elp'
     self.package.save(filename) # This can change the package name
     client.alert(_(u'Package saved to: %s' % filename))
     if onDone:
         client.sendScript(onDone)
     elif self.package.name != oldName:
         self.webServer.root.putChild(self.package.name, self)
         log.info('Package saved, redirecting client to /%s'
                  % self.package.name)
         client.sendScript('top.location = "/%s"' % \
                           self.package.name.encode('utf8'))
Beispiel #2
0
 def exportWebSite(self, client, filename, webDir, stylesDir):
     """
     Export 'client' to a web site,
     'webDir' is just read from config.webDir
     'stylesDir' is where to copy the style sheet information from
     """
     imagesDir    = webDir.joinpath('images')
     scriptsDir   = webDir.joinpath('scripts')
     templatesDir = webDir.joinpath('templates')
     filename = Path(filename)
     if filename.basename() != self.package.name:
         filename /= self.package.name
     if not filename.exists():
         filename.makedirs()
     elif not filename.isdir():
         client.alert(_(u'Filename %s is a file, cannot replace it') % 
                      filename)
         log.error("Couldn't export web page: "+
                   "Filename %s is a file, cannot replace it" % filename)
         return
     else:
         filename.rmtree()
         filename.mkdir()
     websiteExport = WebsiteExport(stylesDir, filename, 
                                   imagesDir, scriptsDir, templatesDir)
     websiteExport.export(self.package)
     self._startFile(filename)
Beispiel #3
0
def launchBrowser(config, packageName):
    """
    Launch the configured webbrowser for this platform
    """
    url = u'%s/%s' % (G.application.exeAppUri, quote(packageName))
    log.info(u"url " + url)
    dfbrw=mywebbrowser.get()
    withdefaultbrowser=True
    if config.browser!=None:
        try:
            config.browser = mywebbrowser.get(config.browser)
            if not config.browser.open(url):
                log.error("Unable to open defined browser: " + config.browser.name)
                withdefaultbrowser = True
            else:
                withdefaultbrowser = False
        except:
            browser_path = Path(config.browser)
            if browser_path.exists():
                log.info(u"path browser " + browser_path.abspath())
                mywebbrowser.register("custom-browser" , None, mywebbrowser.BackgroundBrowser(browser_path.abspath()), -1)
                config.browser = mywebbrowser.get("custom-browser")
                if not config.browser.open(url):
                    log.error("Unable to open custom defined browser: " + browser_path.abspath())
                    withdefaultbrowser=True
                else:
                    withdefaultbrowser=False   
    if withdefaultbrowser:
        config.browser = dfbrw
        config.browser.open(url, new=0, autoraise=True)
    if hasattr(config.browser, "name"):
        log.info(u"Defined Browser: " + config.browser.name)
Beispiel #4
0
 def handleSavePackage(self, client, filename=None, onDone=None):
     """
     Save the current package
     'filename' is the filename to save the package to
     'onDone' will be evaled after saving instead or redirecting
     to the new location (in cases of package name changes).
     (This is used where the user goes file|open when their 
     package is changed and needs saving)
     """
     filename = Path(filename)
     saveDir  = filename.dirname()
     if saveDir and not saveDir.isdir():
         client.alert(_(u'Cannot access directory named ') + unicode(saveDir) + _(u'. Please use ASCII names.'))
         return
     oldName = self.package.name
     if not filename:
         filename = self.package.filename
         assert (filename, 'Somehow save was called without a filename on a package that has no default filename.')
     filename = self.b4save(client, filename, '.elp', _(u'SAVE FAILED!'))
     try:
         self.package.save(filename) # This can change the package name
         (self.config.configDir/'unsavedWork.elp').remove()
     except Exception, e:
         client.alert(_('SAVE FAILED!\n%s' % str(e)))
         raise
Beispiel #5
0
 def testUpgradeAppDir(self):
     """
     Tests that config files with
     'appDataDir' are upgraded to 'configDir'
     """
     # Write the old style config file
     configPath = Path(u'test.exe.conf')
     if configPath.exists():
         configPath.remove()
     oldParser = ConfigParser()
     system = oldParser.addSection('system')
     system.appDataDir = 'my old app data dir'
     oldParser.write(configPath)
     del system
     del oldParser
     # Make the config instance load it
     Config._getConfigPathOptions = lambda self: ['test.exe.conf']
     myconfig = Config()
     myconfig.loadSettings()
     # Check if it reads the old value into the new variable
     assert not hasattr(myconfig, 'appDataDir')
     self.assertEquals(myconfig.configPath, 'test.exe.conf')
     self.assertEquals(myconfig.configDir, 'my old app data dir')
     # Check if it has upgraded the file and added in some nice default values
     newParser = ConfigParser()
     newParser.read(configPath)
     self.assertEquals(newParser.system.configDir, 'my old app data dir')
Beispiel #6
0
 def loadSettings(self):
     """
     Loads the settings from the exe.conf file.
     Overrides the defaults set in __init__
     """
     def defVal(dummy, option):
         """If something is not in the config file, just use the default in
         'self'"""
         return getattr(self, option)
     self.configParser.defaultValue = defVal
     self.upgradeFile()
     if self.configParser.has_section('system'):
         system = self.configParser.system
         self.webDir         = Path(system.webDir)
         self.xulDir         = Path(system.xulDir)
         self.localeDir      = Path(system.localeDir)
         self.port           = int(system.port)
         self.browserPath    = Path(system.browserPath)
         self.dataDir        = Path(system.dataDir)
         self.configDir      = Path(system.configDir)
     if not self.dataDir.isdir():
         self.dataDir = tempfile.gettempdir()
     self.webDir = self.webDir.expand().abspath()
     if not self.configDir.exists():
         self.configDir.mkdir()
     if self.configParser.has_section('user'):
         if self.configParser.user.has_option('locale'):
             self.locale = self.configParser.user.locale
     self.recentProjects = []
     if self.configParser.has_section('recent_projects'):
         recentProjectsSection = self.configParser.recent_projects
         for key, path in recentProjectsSection.items():
             self.recentProjects.append(path)
     self.locale = chooseDefaultLocale(self.localeDir)
 def _setupConfigFile(self, configParser):
     """
     Override this to setup any customised config
     settings
     """
     # Set up the system section
     system = configParser.addSection('system')
     system.exePath = 'exe/exe'
     system.exeDir = 'exe'
     system.webDir = 'exe/webui'
     system.localeDir = 'exe/locale'
     system.configDir = 'tmp'
     system.port = 8081
     # Make a temporary dir where we can save packages and exports etc
     tmpDir = Path('tmp')
     if not tmpDir.exists():
         tmpDir.mkdir()
     dataDir = tmpDir / 'data'
     if not dataDir.exists():
         dataDir.mkdir()
     system.dataDir = dataDir
     system.browserPath = 'not really used in tests so far'
     # Setup the logging section
     logging = configParser.addSection('logging')
     logging.root = 'DEBUG'
Beispiel #8
0
    def uploadFile(self):
        """Store pdf in package, gets sides from pdf, if self.sides
        isn't empty
        """
        filePath = self.path
        log.debug(u"uploadFile " + unicode(filePath))
        if not self.parentNode or not self.parentNode.package:
            log.error("something is wrong with the file")
        ## replace all non-digits and non-usefull stuff with ''
        self.pages = sub("[^\d,-]", "", self.pages)
        if self.pages != "":
            input = PdfFileReader(file(filePath, "rb"))
            lastPage = input.getNumPages() - 1  # last page
            toimport = PdfIdevice.__parseImportPages(self.pages, lastPage)
            log.debug("Parsed pages: " + str(toimport))
            output = PdfFileWriter()

            for page in toimport:
                output.addPage(input.getPage(page))
            log.debug("Found pages to import %s" % toimport)
            tmp = os.tmpnam() + ".pdf"
            log.debug("Tempfile is %s" % tmp)
            outputStream = file(tmp, "wb")
            output.write(outputStream)
            outputStream.close()
            resourceFile = Path(tmp)
            self.file = Resource(self, resourceFile)
            log.debug("Uploaded %s, pages: %s" % (tmp, toimport))
            os.remove(tmp)
            filePath = tmp
        resourceFile = Path(filePath)
        if resourceFile.isfile():
            self.file = Resource(self, resourceFile)
            log.debug(u"uploaded " + self.path)
Beispiel #9
0
def themeHasConfigXML(style):
    themePath = Path(G.application.config.stylesDir / style)
    themeXMLFile = themePath.joinpath("config.xml")
    themeHasXML = False
    if themeXMLFile.exists():
        themeHasXML = True
    return themeHasXML
Beispiel #10
0
 def __setConfigPath(self):
     """
     sets self.configPath to the filename of the config file that we'll
     use.
     In descendant classes set self.configFileOptions to a list
     of directories where the configDir should be in order of preference.
     If no config files can be found in these dirs, it will
     force creation of the config file in the top dir
     """
     # If there's an EXECONF environment variable, use it
     self.configPath = None
     configFileOptions = map(Path, self._getConfigPathOptions())
     if "EXECONF" in os.environ:
         envconf = Path(os.environ["EXECONF"])
         if envconf.isfile():
             self.configPath = os.environ["EXECONF"]
     # Otherwise find the most appropriate existing file
     if self.configPath is None:
         for confPath in configFileOptions:
             if confPath.isfile():
                 self.configPath = confPath
                 break
         else:
             # If no config files exist, create and use the
             # first one on the list
             self.configPath = configFileOptions[0]
             folder = self.configPath.abspath().dirname()
             if not folder.exists():
                 folder.makedirs()
             self.configPath.touch()
     # Now make our configParser
     self.configParser.read(self.configPath)
     self.configParser.autoWrite = True
Beispiel #11
0
 def handleSavePackage(self, client, filename=None, onDone=None):
     """
     Save the current package
     'filename' is the filename to save the package to
     'onDone' will be evaled after saving instead or redirecting
     to the new location (in cases of package name changes).
     (This is used where the user goes file|open when their 
     package is changed and needs saving)
     """
     filename = Path(filename)
     saveDir  = filename.dirname()
     if saveDir and not saveDir.isdir():
         client.alert(_(u'Cannot access directory named ') + unicode(saveDir) + _(u'. Please use ASCII names.'))
         return
     oldName = self.package.name
     # If the script is not passing a filename to us,
     # Then use the last filename that the package was loaded from/saved to
     if not filename:
         filename = self.package.filename
         assert filename, 'Somehow save was called without a filename on a package that has no default filename.'
     # Add the extension if its not already there and give message if not saved
     filename = self.b4save(client, filename, '.elp', _(u'SAVE FAILED!'))
     try:
         self.package.save(filename) # This can change the package name
     except Exception, e:
         client.alert(_('SAVE FAILED!\n%s' % str(e)))
         raise
    def _process(self, request):
        """
        Delegates processing of args to blocks
        """  
        # Still need to call parent (mainpage.py) process
        # because the idevice pane needs to know that new idevices have been
        # added/edited..
        self.parent.process(request)
        if ("action" in request.args and 
            request.args["action"][0] == u"saveChange"):
            log.debug(u"process savachange:::::")
            self.package.save()
            log.debug(u"package name: " + self.package.name)
        for block in self.blocks:
            block.process(request)
        # now that each block and corresponding elements have been processed,
        # it's finally safe to remove any images/etc which made it into 
        # tinyMCE's previews directory, as they have now had their 
        # corresponding resources created:
        webDir     = Path(G.application.tempWebDir) 
        previewDir  = webDir.joinpath('previews')
        for root, dirs, files in os.walk(previewDir, topdown=False): 
            for name in files: 
                os.remove(os.path.join(root, name))

        log.debug(u"After authoringPage process" + repr(request.args))
 def render_POST(self, request):
     """
     function replaced by nevow_clientToServerEvent to avoid POST message
     """
     log.debug("render_POST " + repr(request.args))
     data = {}
     try:
         locale = request.args['locale'][0]
         self.config.locale = locale
         self.config.locales[locale].install(unicode=True)
         self.config.configParser.set('user', 'locale', locale)
         internalAnchors = request.args['internalAnchors'][0]
         self.config.internalAnchors = internalAnchors
         self.config.configParser.set('user', 'internalAnchors', internalAnchors)
         browser = request.args['browser'][0]
         if browser == "None":
             browser = None
         try:
             self.config.browser = mywebbrowser.get(browser)
         except Exception as e:
             browser_path = Path(browser)
             if browser_path.exists():
                 mywebbrowser.register('custom-browser' , None, mywebbrowser.BackgroundBrowser(browser_path.abspath()), -1)
                 self.config.browser = mywebbrowser.get('custom-browser')
             else:
                 raise e
         self.config.configParser.set('system', 'browser', browser)
         showWizardOnStart = request.args['showWizardOnStart'][0]
         self.config.showWizardOnStart = showWizardOnStart
         self.config.configParser.set('user', 'showWizardOnStart', showWizardOnStart)
     except Exception as e:
         log.exception(e)
         return json.dumps({'success': False, 'errorMessage': _("Failed to save preferences wizard")})
     return json.dumps({'success': True, 'data': data})
Beispiel #14
0
 def handleExtractPackage(self, client, filename):
     """
     Create a new package consisting of the current node and export
     """
     filename  = Path(filename)
     saveDir = filename.dirname()
     if saveDir and not saveDir.exists():
         client.alert(_(u'Cannot access directory named ') +
                      unicode(saveDir) +
                      _(u'. Please use ASCII names.'))
         return
     if not filename.lower().endswith('.elp'):
         filename += '.elp'
     if Path(filename).exists():
         client.alert(_(u'EXPORT FAILED.\n"%s" already exists.\n'
                         'Please try again with '
                         'a different filename') % filename)
         return
     package = Package(filename.namebase)
     package.style  = self.package.style
     package.author = self.package.author
     extractNode  = self.package.currentNode.clone()
     extractNode.mergeIntoPackage(package)
     package.root = package.currentNode = extractNode
     package.save(filename)
     client.alert(_(u'Package saved to: %s' % filename))
Beispiel #15
0
 def exportSinglePage(self, client, filename, webDir, stylesDir):
     """
     Export 'client' to a single web page,
     'webDir' is just read from config.webDir
     'stylesDir' is where to copy the style sheet information from
     """
     imagesDir    = webDir.joinpath('images')
     scriptsDir   = webDir.joinpath('scripts')
     templatesDir = webDir.joinpath('templates')
     filename = Path(filename)
     if filename.basename() != self.package.name:
         filename /= self.package.name
     if not filename.exists():
         filename.makedirs()
     elif not filename.isdir():
         client.alert(_(u'Filename %s is a file, cannot replace it') % 
                      filename)
         log.error("Couldn't export web page: "+
                   "Filename %s is a file, cannot replace it" % filename)
         return
     else:
         try:
             filename.rmtree()
             filename.mkdir()
         except Exception, e:
             client.alert(_('There was an error in the export:\n%s') % str(e))
             return
    def __init__(self, config, styleDir, filename, prefix="", report=False, skipNavigation=False, ustadMobileMode=False, ustadMobileTestMode=False):
        #Added ustadMobileTestMode for Course Test Mode.
        """
        'stylesDir' is the directory where we can copy the stylesheets from
        'outputDir' is the directory that will be [over]written
        with the website
        """
        

        self.config       = config
        self.imagesDir    = config.webDir/"images"
        self.scriptsDir   = config.webDir/"scripts"
        self.cssDir       = config.webDir/"css"
        self.templatesDir = config.webDir/"templates"
        self.stylesDir    = Path(styleDir)
        self.filename     = Path(filename)
        self.pages        = []
        self.prefix       = prefix
        self.report       = report
        self.skipNavigation = skipNavigation
        self.ustadMobileMode = ustadMobileMode  
        self.ustadMobileTestMode = ustadMobileTestMode  #Added for Course Test Mode
        self.styleSecureMode = config.styleSecureMode

        self.config          = config
        self.imagesDir       = config.webDir/"images"
        self.scriptsDir      = config.webDir/"scripts"
        self.cssDir          = config.webDir/"css"
        self.templatesDir    = config.webDir/"templates"
        self.stylesDir       = Path(styleDir)
        self.filename        = Path(filename)
        self.pages           = []
        self.prefix          = prefix
        self.report          = report
Beispiel #17
0
 def handleExport(self, client, exportType, filename):
     """
     Called by js. 
     Exports the current package to one of the above formats
     'exportType' can be one of 'singlePage' 'webSite' 'zipFile'
                  'textFile' or 'scorm'
     'filename' is a file for scorm pages, and a directory for websites
     """ 
     webDir     = Path(self.config.webDir)
     stylesDir  = webDir.joinpath('style', self.package.style)
     exportDir  = Path(filename).dirname()
     if exportDir and not exportDir.exists():
         client.alert(_(u'Cannot access directory named ') +
                      unicode(exportDir) +
                      _(u'. Please use ASCII names.'))
         return
     if exportType == 'singlePage':
         self.exportSinglePage(client, filename, webDir, stylesDir)
     elif exportType == 'webSite':
         self.exportWebSite(client, filename, stylesDir)
     elif exportType == 'zipFile':
         self.exportWebZip(client, filename, stylesDir)
     elif exportType == 'textFile':
         self.exportText(client, filename)
     elif exportType == "scorm":
         self.exportScorm(client, filename, stylesDir, "scorm1.2")
     elif exportType == "scorm2004":
         self.exportScorm(client, filename, stylesDir, "scorm2004")
     else:
         self.exportIMS(client, filename, stylesDir)
Beispiel #18
0
 def handleExtractPackage(self, client, filename, existOk):
     """
     Create a new package consisting of the current node and export
     'existOk' means the user has been informed of existance and ok'd it
     """
     filename  = Path(filename)
     saveDir = filename.dirname()
     if saveDir and not saveDir.exists():
         client.alert(_(u'Cannot access directory named ') + unicode(saveDir) + _(u'. Please use ASCII names.'))
         return
     if not filename.lower().endswith('.elp'):
         filename += '.elp'
     if Path(filename).exists() and existOk != 'true':
         msg = _(u'"%s" already exists.\nPlease try again with a different filename') % filename
         client.alert(_(u'EXTRACT FAILED!\n%s' % msg))
         return
     try:
         package = Package(filename.namebase)
         package.style  = self.package.style
         package.author = self.package.author
         extractNode  = self.package.currentNode.clone()
         extractNode.mergeIntoPackage(package)
         package.root = package.currentNode = extractNode
         package.save(filename)
     except Exception, e:
         client.alert(_('EXTRACT FAILED!\n%s' % str(e)))
         raise
Beispiel #19
0
 def testUpgradeTo0_20(self):
     """
     Creates a package similar to what 0.19 would
     and tests if it upgrades ok
     """
     fn = Path('0.19 resources upgrade test.elp')
     assert fn.isfile() or fn.islink()
     package = self.package.__class__.load(fn)
     assert hasattr(package, 'resources')
     assert len(package.resources) == 8, len(package.resources)
     for checksum, resources in package.resources.items():
         storageNames = []
         userNames = []
         for res in resources:
             storageNames.append(res.storageName)
             userNames.append(res.userName)
         assert len(set(storageNames)) == 1, 'Two identical resources have different storage names:\n%s' % storageNames
     allResourceNames = []
     for reses in package.resources.values():
         allResourceNames.append(reses[0].storageName)
     filenames = [path.basename() for path in package.resourceDir.files()]
     withoutDups = set(filenames) - set(allResourceNames)
     assert withoutDups == set([]), "Duplicate files weren't deleted %s" % withoutDups
     assert len(filenames) == len(allResourceNames)
     assert len(filenames) > 0, 'All resources have been deleted!'
Beispiel #20
0
class StandaloneConfig(Config):
    """
    The StandaloneConfig overrides the Config class with ready-to-run specific
    configuration
    """
    
    def _overrideDefaultVals(self):
        """
        Setup with our default settings
        """
        self.exePath = Path(sys.argv[0])
        if self.exePath.isfile():
            self.exePath = self.exePath.dirname()
        exePath = self.exePath
        # Override the default settings
        self.webDir        = exePath
        self.configDir     = exePath/'config'
        self.localeDir     = exePath/'locale'
        self.stylesDir     = Path(exePath/'style').abspath()
        self.styles        = []
        self.lastDir       = exePath

    def _getConfigPathOptions(self):
        """
        Returns the best places for a linux config file
        """
        return [self.configDir/'exe.conf']
Beispiel #21
0
class StandaloneConfig(Config):
    """
    The StandaloneConfig overrides the Config class with ready-to-run specific
    configuration
    """
    def _overrideDefaultVals(self):
        """
        Setup with our default settings
        """
        self.exePath = Path(sys.argv[0])
        if self.exePath.isfile():
            self.exePath = self.exePath.dirname()
        exePath = self.exePath
        self.webDir        = exePath
        self.dataDir       = exePath/'packages'
        if not self.dataDir.exists():
            self.dataDir.makedirs()
        self.configDir     = exePath/'config'
        self.localeDir     = exePath/'locale'
        self.xulrunnerPath = exePath/'xulrunner/xulrunner'
        self.styles        = []
        self.browserPath = exePath/'firefox'/'firefox.exe'
    def _getConfigPathOptions(self):
        """
        Returns the best places for a linux config file
        """
        return [self.configDir/'exe.conf']
Beispiel #22
0
 def __setConfigPath(self):
     """
     sets self.configPath to the filename of the config file that we'll
     use.
     In descendant classes set self.configFileOptions to a list
     of directories where the configDir should be in order of preference.
     If no config files can be found in these dirs, it will
     force creation of the config file in the top dir
     """
     self.configPath = None
     configFileOptions = map(Path, self._getConfigPathOptions())
     if "EXECONF" in os.environ:
         envconf = Path(os.environ["EXECONF"])
         if envconf.isfile():
             self.configPath = os.environ["EXECONF"]
     if self.configPath is None:
         for confPath in configFileOptions:
             if confPath.isfile():
                 self.configPath = confPath
                 break
         else:
             self.configPath = configFileOptions[0]
             folder = self.configPath.abspath().dirname()
             if not folder.exists():
                 folder.makedirs()
             self.configPath.touch()
     self.configParser.read(self.configPath)
     self.configParser.autoWrite = True
Beispiel #23
0
 def setFlash(self, flashPath):
     """
     Store the image in the package
     Needs to be in a package to work.
     """
     log.debug(u"setFlash "+unicode(flashPath))
     resourceFile = Path(flashPath)
     assert(self.idevice.parentNode,
            'Flash '+self.idevice.id+' has no parentNode')
     assert(self.idevice.parentNode.package,
            'iDevice '+self.idevice.parentNode.id+' has no package')
     if resourceFile.isfile():
         if self.flashResource:
             self.flashResource.delete()
             self.idevice.userResources.remove(self.flashResource)
         try:
             flvDic = FLVReader(resourceFile)
             self.height = flvDic["height"] +30        
             self.width  = flvDic["width"]
             self.flashResource = Resource(self.idevice.parentNode.package,
                                           resourceFile)
             self.idevice.userResources.append(self.flashResource)
         except AssertionError: 
             log.error('File %s is not a flash movie' % resourceFile)
     else:
         log.error('File %s is not a file' % resourceFile)
 def setUp(self):
     """
     Creates an application and
     almost launches it.
     """
     # Make whatever config class that application uses only look for our
     # Set up our customised config file
     logFileName = Path('tmp/app data/test.conf')
     sys.argv[0] = 'exe/exe'
     Config._getConfigPathOptions = lambda s: [logFileName]
     if not logFileName.dirname().exists():
         logFileName.dirname().makedirs()
     confParser = ConfigParser()
     self._setupConfigFile(confParser)
     confParser.write(logFileName)
     # Start up the app and friends
     if G.application is None:
         G.application = Application()
         
     self.app = G.application
     G.application = self.app
     self.app.loadConfiguration()
     self.app.preLaunch()
     self.client = FakeClient()
     self.package = Package('temp')
     self.session = FakeSession()
     self.app.webServer.root.bindNewPackage(self.package, self.session)
     self.mainpage = self.app.webServer.root.mainpages[self.session.uid]['temp']
     self.mainpage.idevicePane.client = self.client
 def handleExternalResources(self, html):
     html_content_lower = html.lower()
     start_index = 0
     start_index = self._findNextTagStart(html_content_lower, start_index, ['img'])
     while start_index != -1:
         res_src = self._getSrcForTag(html, start_index)
         if res_src is not None and res_src.startswith("http://"):
             new_file_basename = self.url2ascii(res_src)
             new_file_name = str(self.workingDir/new_file_basename)
             new_file_path = Path(self.workingDir/new_file_basename)
             if new_file_path.exists() is False: 
                 urllib.urlretrieve(res_src, new_file_name)
             
             old_length = len(html)
             html = html.replace(res_src, new_file_name)
             html_content_lower = html.lower()
             new_length = len(html)
             length_difference = old_length - new_length
             start_index += length_difference
             
             
         end_tag_index = html_content_lower.find(">", start_index);
         start_index = self._findNextTagStart(html_content_lower,end_tag_index , ['img'])
     
     return html
Beispiel #26
0
 def __init__(self):
     """
     Initialise
     """
     self.configPath = None
     self.configParser = ConfigParser()
     self.exePath = Path(sys.argv[0]).abspath()
     self.webDir = self.exePath.dirname()
     self.xulDir = self.exePath.dirname()
     self.localeDir = self.exePath.dirname() / "locale"
     self.port = 51235
     self.dataDir = Path(".")
     self.configDir = Path(".")
     self.browserPath = Path("firefox")
     self.locale = chooseDefaultLocale(self.localeDir)
     self.styles = []
     self._overrideDefaultVals()
     self.webDir = Path(self.webDir)
     if not (self.webDir / "scripts").isdir() and (self.webDir / "webui").isdir():
         self.webDir /= "webui"
     self.xulDir = Path(self.xulDir)
     if not (self.xulDir / "scripts").isdir() and (self.xulDir / "xului").isdir():
         self.xulDir /= "xului"
     self.__setConfigPath()
     self._writeDefaultConfigFile()
     self.loadSettings()
     self.setupLogging()
     self.loadStyles()
     self.loadLocales()
    def doTest(self, ExporterClass):
        """Exports a package with meta data"""
        # Load our test package
        package = Package.load('testPackage.elp')
        # Do the export
        outFilename = Path('scormtest.zip')
        exporter = ExporterClass(self.app.config,
                                 '../exe/webui/style/default', 
                                 outFilename)
        exporter.export(package)
        # Check that it made a nice zip file
        assert outFilename.exists()
        # See if the manifest file was created
        zipped = ZipFile(outFilename)
        filenames = zipped.namelist()
        assert 'imsmanifest.xml' in filenames, filenames
        self._testManifest(zipped.read('imsmanifest.xml'))

        # Test that all the node's html files have been generated
        pagenodes  = Set([p.node for p in exporter.pages])
        othernodes = Set(self._getNodes([], package.root))
        assert pagenodes == othernodes

        for page in exporter.pages:
            self._testPage(page, zipped)

        # Clean up
        zipped.close()
Beispiel #28
0
 def handleExtractPackage(self, client, filename, existOk):
     """
     Create a new package consisting of the current node and export
     'existOk' means the user has been informed of existance and ok'd it
     """
     filename = Path(filename)
     saveDir = filename.dirname()
     if saveDir and not saveDir.exists():
         client.alert(_(u"Cannot access directory named ") + unicode(saveDir) + _(u". Please use ASCII names."))
         return
     if not filename.lower().endswith(".elp"):
         filename += ".elp"
     if Path(filename).exists() and existOk != "true":
         msg = _(u'"%s" already exists.\nPlease try again with a different filename') % filename
         client.alert(_(u"EXTRACT FAILED!\n%s" % msg))
         return
     try:
         newPackage = self.package.extractNode()
         newNode = newPackage.root
         if newNode:
             newNode.RenamedNodePath(isExtract=True)
         newPackage.save(filename)
     except Exception, e:
         client.alert(_("EXTRACT FAILED!\n%s" % str(e)))
         raise
Beispiel #29
0
 def updateIdevices(self):
     """
     Update new style HTML/Javascript idevices in user directory.
     Copy only when the files are newer
     """
     idevice_src_dir=self.webDir/'templates'/'idevices'
     idevice_dst_dir=self.configDir/"idevices"
     for dir, subdirs, files in os.walk(idevice_src_dir):
         reldirpath = idevice_src_dir.relpathto(dir)
         for file in files:
             dst_file = idevice_dst_dir/reldirpath/file
             src_file = Path(dir)/file
             src_mtime = src_file.mtime
             if not dst_file.exists() or src_mtime > dst_file.mtime:
                 #check dir
                 if not dst_file.dirname().isdir():
                     dst_file.dirname().makedirs()
                 
                 if file == "idevice.xml" and dst_file.exists():
                     #We need to update the file whilst preserving if it's visible or not....
                     dst_xml = etree.parse(dst_file).getroot()
                     ns = dst_xml.nsmap.get(None)
                     visible_val = dst_xml.find(".//{%s}visible" % ns).text
                     src_xml = etree.parse(src_file)
                     src_xml.find(".//{%s}visible" % ns).text = visible_val
                     dst_fd = open(dst_file, "w")
                     dst_fd.write(etree.tostring(src_xml, encoding = "UTF-8", pretty_print = True)) 
                     dst_fd.flush()
                     dst_fd.close() 
                 else:
                     src_file.copy(dst_file)
Beispiel #30
0
    def loadSettings(self):
        """
        Loads the settings from the exe.conf file.
        Overrides the defaults set in __init__
        """

        def defVal(dummy, option):
            """If something is not in the config file, just use the default in
            'self'"""
            return getattr(self, option)

        self.configParser.defaultValue = defVal
        self.upgradeFile()
        if self.configParser.has_section("system"):
            system = self.configParser.system
            self.webDir = Path(system.webDir)
            self.xulDir = Path(system.xulDir)
            self.localeDir = Path(system.localeDir)
            self.port = int(system.port)
            self.browserPath = Path(system.browserPath)
            self.dataDir = Path(system.dataDir)
            self.configDir = Path(system.configDir)
        if not self.dataDir.isdir():
            self.dataDir = tempfile.gettempdir()
        self.webDir = self.webDir.expand().abspath()
        if not self.configDir.exists():
            self.configDir.mkdir()
        if self.configParser.has_section("user"):
            if self.configParser.user.has_option("locale"):
                self.locale = self.configParser.user.locale
                return
        self.locale = chooseDefaultLocale(self.localeDir)
Beispiel #31
0
    def render(self, request):
        if "sendWhat" in request.args:
            if request.args['sendWhat'][0] == 'dirs':
                pathdir = Path(unquote(
                    request.args['node'][0].decode('utf-8')))
                l = []
                if pathdir == '/' and sys.platform[:3] == "win":
                    for d in get_drives():
                        try:
                            if is_readable(Path(d)):
                                icon = None
                            else:
                                icon = '../jsui/extjs/resources/themes/images/gray/grid/hmenu-lock.gif'
                            l.append({
                                "realtext": d,
                                "text": d,
                                "id": d + '\\',
                                "icon": icon
                            })
                        except:
                            pass
                else:
                    for d in pathdir.dirs():
                        try:
                            if not d.name.startswith(
                                    '.') or sys.platform[:3] == "win":
                                if not iswinlink(d.abspath()):
                                    if is_readable(d):
                                        icon = None
                                    else:
                                        icon = '../jsui/extjs/resources/themes/images/gray/grid/hmenu-lock.gif'
                                    l.append({
                                        "realtext": d.name,
                                        "text": getname(d),
                                        "id": d.abspath(),
                                        "icon": icon
                                    })
                        except:
                            pass
            elif request.args['sendWhat'][0] == 'both':
                pathdir = Path(unquote(request.args['dir'][0].decode('utf-8')))
                items = []
                if pathdir == '/' and sys.platform[:3] == "win":
                    for drive in get_drives():
                        d = Path(drive + '\\')
                        items.append({
                            "name": drive,
                            "realname": drive + '\\',
                            "size": 0,
                            "type": 'directory',
                            "modified": 0,
                            "is_readable": is_readable(d),
                            "is_writable": is_writable(d)
                        })
                else:
                    parent = pathdir.parent
                    if (parent == pathdir):
                        realname = '/'
                    else:
                        realname = parent.abspath()
                    items.append({
                        "name": '.',
                        "realname": pathdir.abspath(),
                        "size": pathdir.size,
                        "type": "directory",
                        "modified": int(pathdir.mtime),
                        "is_readable": is_readable(pathdir),
                        "is_writable": is_writable(pathdir)
                    })
                    items.append({
                        "name": '..',
                        "realname": realname,
                        "size": parent.size,
                        "type": "directory",
                        "modified": int(parent.mtime),
                        "is_readable": is_readable(parent),
                        "is_writable": is_writable(parent)
                    })
                    try:
                        for d in pathdir.listdir():
                            try:
                                if not d.name.startswith(
                                        '.') or sys.platform[:3] == "win":
                                    if not iswinlink(d.abspath()):
                                        if d.isdir():
                                            pathtype = "directory"
                                        elif d.isfile():
                                            if is_readable(d):
                                                pathtype = repr(
                                                    mimetypes.guess_type(
                                                        d.name, False)[0])
                                            else:
                                                pathtype = "file"
                                        elif d.islink():
                                            pathtype = "link"
                                        else:
                                            pathtype = "None"
                                        items.append({
                                            "name":
                                            getname(d),
                                            "realname":
                                            d.abspath(),
                                            "size":
                                            d.size,
                                            "type":
                                            pathtype,
                                            "modified":
                                            int(d.mtime),
                                            "is_readable":
                                            is_readable(d),
                                            "is_writable":
                                            is_writable(d)
                                        })
                            except:
                                pass
                        G.application.config.lastDir = pathdir
                    except:
                        pass
                l = {
                    "totalCount": len(items),
                    'results': len(items),
                    'items': items
                }
            return json.dumps(l).encode('utf-8')
        elif "query" in request.args:
            query = request.args['query'][0]
            pathdir = Path(unquote(request.args['dir'][0].decode('utf-8')))
            items = []
            if pathdir == '/' and sys.platform[:3] == "win":
                for d in get_drives():
                    items.append({
                        "name": d,
                        "realname": d + '\\',
                        "size": 0,
                        "type": 'directory',
                        "modified": 0
                    })
            else:
                parent = pathdir.parent
                if (parent == pathdir):
                    realname = '/'
                else:
                    realname = parent.abspath()
                for d in pathdir.listdir():
                    try:
                        if d.isdir():
                            pathtype = "directory"
                        elif d.isfile():
                            if is_readable(d):
                                pathtype = repr(
                                    mimetypes.guess_type(d.name, False)[0])
                            else:
                                pathtype = "file"
                        elif d.islink():
                            pathtype = "link"
                        else:
                            pathtype = "None"
                        if d.name.startswith(query):
                            items.append({
                                "name": getname(d),
                                "realname": d.abspath(),
                                "size": d.size,
                                "type": pathtype,
                                "modified": int(d.mtime),
                                "is_readable": is_readable(d),
                                "is_writable": is_writable(d)
                            })
                    except:
                        pass

            l = {
                "totalCount": len(items),
                'results': len(items),
                'items': items
            }
            return json.dumps(l).encode('utf-8')
        return ""
Beispiel #32
0
def ideviceHeader(e, style, mode):
    dT = getExportDocType()
    lb = "\n"  #Line breaks
    #Default HTML tags:
    articleTag = "div"
    headerTag = "div"
    titleTag = "h2"
    if dT == "HTML5":
        articleTag = "article"
        headerTag = "header"
        titleTag = "h1"

    themePath = Path(G.application.config.stylesDir / style)
    themeXMLFile = themePath.joinpath("config.xml")
    themeHasXML = themeHasConfigXML(style)

    w = ''  # Common wrapper
    o = ''  # Old HTML (themes with no config.xml file)
    h = ''  # New HTML
    w2 = ''
    eEm = ''
    if e.idevice.emphasis > 0:
        w2 = '<div class="iDevice_inner">' + lb
        w2 += '<div class="iDevice_content_wrapper">' + lb
        eEm = ' em_iDevice'

    if mode == "preview" and themeHasXML:
        w += '<' + articleTag + ' class="iDevice_wrapper ' + e.idevice.klass + eEm + '" id="id' + e.id + '">' + lb

    w += u"<div class=\"iDevice emphasis" + unicode(e.idevice.emphasis) + "\" "
    if mode == "preview":
        w += u"ondblclick=\"submitLink('edit', " + e.id + ", 0);\""
    w += ">" + lb

    if e.idevice.emphasis > 0:
        h += '<' + headerTag + ' class="iDevice_header"'
        if e.idevice.icon:
            displayIcon = True
            # The following lines should be replaced by something like:
            '''
            if hasattr(e.idevice, 'originalicon'):
                if e.idevice.icon==e.idevice.originalicon:
                    displayIcon = False
            '''
            k = e.idevice.klass
            i = e.idevice.icon
            if (k == 'ListaIdevice' and i == 'question') or (
                    k == 'CasestudyIdevice' and i == 'casestudy'
            ) or (k == 'GalleryIdevice' and i == 'gallery') or (
                    k == 'ClozeIdevice' and i == 'question'
            ) or (k == 'ReflectionIdevice' and i == 'reflection') or (
                    k == 'QuizTestIdevice' and i == 'question') or (
                        k == 'TrueFalseIdevice' and i == 'question') or (
                            k == 'MultiSelectIdevice'
                            and i == 'question') or (k == 'MultichoiceIdevice'
                                                     and i == 'question'):
                displayIcon = False
            # /end
            iconPath = '/style/' + style + '/icon_' + e.idevice.icon + '.gif'
            if mode == "view":
                iconPath = 'icon_' + e.idevice.icon + '.gif'
            myIcon = themePath.joinpath("icon_" + e.idevice.icon + ".gif")
            if myIcon.exists():
                o += u'<img alt="" class="iDevice_icon" src="' + iconPath + '" />'
            if (e.idevice.icon + "Idevice") != e.idevice.klass:
                if myIcon.exists() and displayIcon:
                    h += ' style="background-image:url(' + iconPath + ')"'
        else:
            log.debug("Idevice %s at node %s has no icon" %
                      (e.idevice._title, e.idevice.parentNode._title))
        t = e.idevice.title
        fullT = u'<' + titleTag + ' class="iDeviceTitle">' + t + '</' + titleTag + '>'
        if (t == ""):
            fullT = u'<span class="iDeviceTitle">&nbsp;</span>'
        o += u"<" + titleTag + " class=\"iDeviceTitle\">" + t + "</" + titleTag + ">"
        h += '>'
        h += fullT
        h += '</' + headerTag + '>' + lb

    if e.idevice.emphasis <= 0:
        h = ""
        o = ""
    if themeHasXML:
        return w + h + w2
    else:
        return w + o + w2
Beispiel #33
0
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
# ===========================================================================

''' Add to corresponding po file the tinymce lang strings
    Depends on demjson python module to parse json and polib. "apt-get install python-demjson python-polib"
'''
from exe.engine.path import Path
import demjson
import polib

if __name__ == '__main__':
    basedir = Path() / 'exe' / 'webui' / 'scripts' / 'tinymce_3.5.7' / 'jscripts' / 'tiny_mce'
    pos = {}
    for path in basedir.walk('en*.js'):
        pathdir = path.dirname()
        f = path.bytes()
        s = '{' + f.partition('{')[2]
        s = s.rpartition('}')[0] + '}'
        srcjson = demjson.decode(s)
        for pathfile in pathdir.files():
            if pathfile.basename() not in ['en.js', 'en_dlg.js'] and len(pathfile.basename()) == len(path.basename()):
                fl = pathfile.bytes()
                sl = '{' + fl.partition('{')[2]
                sl = sl.rpartition('}')[0] + '}'
                langjson = demjson.decode(sl)

                def append_string(string, key, json, srcstring):
Beispiel #34
0
    def copyFiles(self, package):
        """
        Copy all the files used by the website.
        """
        # Copy the style files to the output dir
        # But not nav.css
        if os.path.isdir(self.stylesDir):
            styleFiles = [self.stylesDir / '..' / 'popup_bg.gif']
            styleFiles += self.stylesDir.files("*.*")
            if "nav.css" in styleFiles:
                styleFiles.remove("nav.css")
            self.stylesDir.copylist(styleFiles, self.outputDir)

        # copy the package's resource files
        for resourceFile in package.resourceDir.walkfiles():
            file = package.resourceDir.relpathto(resourceFile)

            if ("/" in file):
                Dir = Path(self.outputDir / file[:file.rindex("/")])

                if not Dir.exists():
                    Dir.makedirs()

                resourceFile.copy(self.outputDir / Dir)
            else:
                resourceFile.copy(self.outputDir)

        listCSSFiles = getFilesCSSToMinify('singlepage', self.stylesDir)
        exportMinFileCSS(listCSSFiles, self.outputDir)

        # copy script files.
        my_style = G.application.config.styleStore.getStyle(package.style)

        # jQuery
        if my_style.hasValidConfig():
            if my_style.get_jquery() == True:
                jsFile = (self.scriptsDir / 'exe_jquery.js')
                jsFile.copyfile(self.outputDir / 'exe_jquery.js')
        else:
            jsFile = (self.scriptsDir / 'exe_jquery.js')
            jsFile.copyfile(self.outputDir / 'exe_jquery.js')

        dT = common.getExportDocType()
        if dT == "HTML5":
            jsFile = (self.scriptsDir / 'exe_html5.js')
            jsFile.copyfile(self.outputDir / 'exe_html5.js')

        # Minify common.js file
        listFiles = getFilesJSToMinify('singlepage', self.scriptsDir)
        exportMinFileJS(listFiles, self.outputDir)

        # Create lang file
        langFile = open(self.outputDir + '/common_i18n.js', "w")
        langFile.write(common.getJavaScriptStrings(False))
        langFile.close()

        # Incluide eXe's icon if the Style doesn't have one
        themePath = Path(G.application.config.stylesDir / package.style)
        themeFavicon = themePath.joinpath("favicon.ico")
        if not themeFavicon.exists():
            faviconFile = (self.imagesDir / 'favicon.ico')
            faviconFile.copyfile(self.outputDir / 'favicon.ico')

        #JR Metemos los reproductores necesarios
        self.compruebaReproductores(self.page.node)

        if package.license == "license GFDL":
            # include a copy of the GNU Free Documentation Licence
            ext = 'html'
            if G.application.config.cutFileName == "1":
                ext = 'htm'
            (self.templatesDir / 'fdl' + '.' +
             ext).copyfile(self.outputDir / 'fdl' + '.' + ext)
Beispiel #35
0
 def __renderIcons(self, style):
     """
     Return xhtml string for dispay all icons
     """
     iconpath  = Path(G.application.config.stylesDir/style)
     iconfiles = iconpath.files("icon_*")
     html = '<div id="styleIcons"><div style="height:300px;overflow:auto">'
     
     for iconfile in iconfiles:
         iconname = iconfile.namebase
         icon     = iconname.split("_", 1)[1]
         
         iconExists = False
         iconExtension = "gif"
         myIcon = Path(G.application.config.stylesDir/style/iconname + ".gif")
         if myIcon.exists():
             iconExists = True
             iconValue = icon+'.'+iconExtension  
             iconSrc = '/style/%s/icon_%s' % (style, iconValue)
         else:
             myIcon = Path(G.application.config.stylesDir/style/iconname + ".png")
             if myIcon.exists():
                 iconExists = True 
                 iconExtension = "png"
                 iconValue = icon+'.'+iconExtension
                 iconSrc = '/style/%s/icon_%s' % (style, iconValue)
             else:
                 myIcon = Path(G.application.config.stylesDir/style/iconname + ".svg")
                 if myIcon.exists():
                     iconExists = True 
                     iconExtension = "svg"
                     iconValue = icon+'.'+iconExtension
                     iconSrc = '/style/%s/icon_%s' % (style, iconValue)
         
         if iconExists:
             filename = "/style/%s/%s.%s" % (style, iconname, iconExtension)
             html += u'<div style="float:left; text-align:center; width:105px;\n'
             html += u'margin-right:10px; margin-bottom:15px" > '
             html += u'<img src="%s" \n' % filename
             html += u"style=\"border:1px solid #E8E8E8;padding:5px;cursor:pointer;max-width:60px;max-height:60px;height:auto\" onclick=\"window[0].selectStyleIcon('%s',this, '%s', '%s')\" title=\"%s.%s\">\n" % (icon, iconSrc, self.id, icon ,iconExtension)
             html += u'<br /><span style="display:inline-block;width:100px;overflow:hidden;text-overflow:ellipsis">%s.%s</span></div>\n' % (icon, iconExtension)
     
     html += '</div></div>'
     
     return html
Beispiel #36
0
    def __renderHeader(self):
        #TinyMCE lang (user preference)
        myPreferencesPage = self.webServer.preferences
        """Generates the header for AuthoringPage"""
        html = common.docType()
        #################################################################################
        #################################################################################

        html += u'<html xmlns="http://www.w3.org/1999/xhtml" lang="' + myPreferencesPage.getSelectedLanguage(
        ) + '">\n'
        html += u'<head>\n'
        html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe.css\" />"

        # Use the Style's base.css file if it exists
        themePath = Path(G.application.config.stylesDir / self.package.style)
        themeBaseCSS = themePath.joinpath("base.css")
        if themeBaseCSS.exists():
            html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/base.css\" />" % self.package.style
        else:
            html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/base.css\" />"

        html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe_wikipedia.css\" />"
        html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_effects/exe_effects.css\" />"
        html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_highlighter/exe_highlighter.css\" />"
        html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_games/exe_games.css\" />"
        html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/content.css\" />" % self.package.style
        if G.application.config.assumeMediaPlugins:
            html += u"<script type=\"text/javascript\">var exe_assume_media_plugins = true;</script>\n"
        #JR: anado una variable con el estilo
        estilo = u'/style/%s/content.css' % self.package.style
        html += common.getJavaScriptStrings()
        # The games require additional strings
        html += common.getGamesJavaScriptStrings()
        html += u"<script type=\"text/javascript\">"
        html += u"var exe_style = '%s';" % estilo
        # editorpane.py uses exe_style_dirname to auto-select the current style (just a provisional solution)
        html += u"var exe_style_dirname = '%s'; top.exe_style_dirname = exe_style_dirname;" % self.package.style
        html += u"var exe_package_name='" + self.package.name + "';"
        html += 'var exe_export_format="' + common.getExportDocType(
        ) + '".toLowerCase();'
        html += 'var exe_editor_mode="' + myPreferencesPage.getEditorMode(
        ) + '";'
        html += 'var exe_editor_version="' + myPreferencesPage.getEditorVersion(
        ) + '";'
        html += '</script>\n'
        html += u'<script type="text/javascript" src="../jsui/native.history.js"></script>\n'
        html += u'<script type="text/javascript" src="/scripts/authoring.js"></script>\n'
        html += u'<script type="text/javascript" src="/scripts/exe_jquery.js"></script>\n'
        html += u'<script type="text/javascript" src="/scripts/exe_lightbox/exe_lightbox.js"></script>\n'
        html += u'<script type="text/javascript" src="/scripts/exe_effects/exe_effects.js"></script>\n'
        html += u'<script type="text/javascript" src="/scripts/exe_highlighter/exe_highlighter.js"></script>\n'
        html += u'<script type="text/javascript" src="/scripts/exe_games/exe_games.js"></script>\n'
        html += u'<script type="text/javascript" src="/scripts/common.js"></script>\n'
        html += '<script type="text/javascript">document.write(decodeURIComponent("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>'
        html += '<script type="text/javascript">document.write(decodeURIComponent("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_settings_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>'
        html += u'<title>"+_("eXe : elearning XHTML editor")+"</title>\n'
        html += u'<meta http-equiv="content-type" content="text/html; '
        html += u' charset=UTF-8" />\n'
        style = G.application.config.styleStore.getStyle(self.package.style)
        if style.hasValidConfig:
            html += style.get_edition_extra_head()
        html += u'</head>\n'
        return html
Beispiel #37
0
    def copyFiles(self, package, outputDir):
        """
        Copy all the files used by the website.
        """

        if os.path.isdir(self.stylesDir):
            # Copy the style files to the output dir
            styleFiles = [self.stylesDir / '..' / 'popup_bg.gif']
            styleFiles += self.stylesDir.files("*.*")
            self.stylesDir.copylist(styleFiles, outputDir)

        # copy the package's resource files
        for resourceFile in package.resourceDir.walkfiles():
            file = package.resourceDir.relpathto(resourceFile)

            if ("/" in file):
                Dir = Path(outputDir / file[:file.rindex("/")])

                if not Dir.exists():
                    Dir.makedirs()

                resourceFile.copy(outputDir / Dir)
            else:
                resourceFile.copy(outputDir)

        listCSSFiles = getFilesCSSToMinify('website', self.stylesDir)
        exportMinFileCSS(listCSSFiles, outputDir)

        # copy script files.
        my_style = G.application.config.styleStore.getStyle(package.style)
        # jQuery
        listFiles = []
        listOutFiles = []
        if my_style.hasValidConfig:
            if my_style.get_jquery() == True:
                jsFile = (self.scriptsDir / 'exe_jquery.js')
                jsFile.copyfile(outputDir / 'exe_jquery.js')
        else:
            listFiles += [self.scriptsDir / 'exe_jquery.js']
            listOutFiles += [outputDir / 'exe_jquery.js']

        # Minify common.js file
        listFiles = getFilesJSToMinify('website', self.scriptsDir)
        exportMinFileJS(listFiles, outputDir)

        # Create lang file
        langFile = open(outputDir + '/common_i18n.js', "w")
        langFile.write(common.getJavaScriptStrings(False))
        langFile.close()
        #dT = common.getExportDocType()
        dT = common.getExportDocType()
        if dT == "HTML5":
            jsFile = (self.scriptsDir / 'exe_html5.js')
            jsFile.copyfile(outputDir / 'exe_html5.js')

        # Incluide eXe's icon if the Style doesn't have one
        themePath = Path(G.application.config.stylesDir / package.style)
        themeFavicon = themePath.joinpath("favicon.ico")
        if not themeFavicon.exists():
            faviconFile = (self.imagesDir / 'favicon.ico')
            faviconFile.copyfile(outputDir / 'favicon.ico')

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        hasGallery = False
        hasFX = False
        hasSH = False
        hasGames = False
        hasWikipedia = False
        isBreak = False
        hasInstructions = False
        hasMediaelement = False
        hasTooltips = False
        hasABCMusic = False
        listIdevicesFiles = []

        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer
                        and hasGallery and hasFX and hasSH and hasGames
                        and hasWikipedia and hasInstructions
                        and hasMediaelement and hasTooltips and hasABCMusic):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'mojomagnify.js' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True
                if not hasGallery:
                    hasGallery = common.ideviceHasGallery(idevice)
                if not hasFX:
                    hasFX = common.ideviceHasFX(idevice)
                if not hasSH:
                    hasSH = common.ideviceHasSH(idevice)
                if not hasGames:
                    hasGames = common.ideviceHasGames(idevice)
                if not hasWikipedia:
                    if 'WikipediaIdevice' == idevice.klass:
                        hasWikipedia = True
                if not hasInstructions:
                    if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                        hasInstructions = True
                if not hasMediaelement:
                    hasMediaelement = common.ideviceHasMediaelement(idevice)
                if not hasTooltips:
                    hasTooltips = common.ideviceHasTooltips(idevice)
                if not hasABCMusic:
                    hasABCMusic = common.ideviceHasABCMusic(idevice)
                if hasattr(idevice, "_iDeviceDir"):
                    listIdevicesFiles.append(
                        (Path(idevice._iDeviceDir) / 'export'))

            common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir)

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(outputDir / 'flowPlayer.swf')
            controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
            controlsfile.copyfile(outputDir / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'mojomagnify.js')
            videofile.copyfile(outputDir / 'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(outputDir / 'xspf_player.swf')
        if hasGallery:
            exeLightbox = (self.scriptsDir / 'exe_lightbox')
            exeLightbox.copyfiles(outputDir)
        if hasFX:
            exeEffects = (self.scriptsDir / 'exe_effects')
            exeEffects.copyfiles(outputDir)
        if hasSH:
            exeSH = (self.scriptsDir / 'exe_highlighter')
            exeSH.copyfiles(outputDir)
        if hasGames:
            exeGames = (self.scriptsDir / 'exe_games')
            exeGames.copyfiles(outputDir)
            # Add game js string to common_i18n
            langGameFile = open(outputDir + '/common_i18n.js', "a")
            langGameFile.write(common.getGamesJavaScriptStrings(False))
            langGameFile.close()
        if hasABCMusic:
            pluginScripts = (self.scriptsDir /
                             'tinymce_4/js/tinymce/plugins/abcmusic/export')
            pluginScripts.copyfiles(outputDir)
        if hasWikipedia:
            wikipediaCSS = (self.cssDir / 'exe_wikipedia.css')
            wikipediaCSS.copyfile(outputDir / 'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self,
                                        outputDir)
            common.copyFileIfNotInStyle('stock-stop.png', self, outputDir)
        if hasMediaelement:
            mediaelement = (self.scriptsDir / 'mediaelement')
            mediaelement.copyfiles(outputDir)
            dT = common.getExportDocType()
            if dT != "HTML5":
                jsFile = (self.scriptsDir / 'exe_html5.js')
                jsFile.copyfile(outputDir / 'exe_html5.js')
        if hasTooltips:
            exe_tooltips = (self.scriptsDir / 'exe_tooltips')
            exe_tooltips.copyfiles(outputDir)

        if hasattr(package, 'exportSource') and package.exportSource:
            (G.application.config.webDir / 'templates' /
             'content.xsd').copyfile(outputDir / 'content.xsd')
            (outputDir / 'content.data').write_bytes(encodeObject(package))
            (outputDir / 'contentv3.xml').write_bytes(
                encodeObjectToXML(package))
        ext = 'html'
        if G.application.config.cutFileName == "1":
            ext = 'htm'
        if package.license == "license GFDL":
            # include a copy of the GNU Free Documentation Licence
            (self.templatesDir / 'fdl' + '.' +
             ext).copyfile(outputDir / 'fdl' + '.' + ext)
Beispiel #38
0
class IMSExport(object):
    """
    Exports an eXe package as a SCORM package
    """
    def __init__(self, config, styleDir, filename):
        """ Initialize
        'styleDir' is the directory from which we will copy our style sheets
        (and some gifs)
        """
        self.config       = config
        self.imagesDir    = config.webDir/"images"
        self.scriptsDir   = config.webDir/"scripts"
        self.templatesDir = config.webDir/"templates"
        self.schemasDir   = config.webDir/"schemas/ims"
        self.styleDir     = Path(styleDir)
        self.filename     = Path(filename)
        self.pages        = []


    def export(self, package):
        """ 
        Export SCORM package
        """
        # First do the export to a temporary directory
        outputDir = TempDirPath()

        # Copy the style sheet files to the output dir
        # But not nav.css
        styleFiles  = [self.styleDir/'..'/'base.css']
        styleFiles += [self.styleDir/'..'/'popup_bg.gif']
        styleFiles += self.styleDir.files("*.css")
        if "nav.css" in styleFiles:
            styleFiles.remove("nav.css")
        styleFiles += self.styleDir.files("*.jpg")
        styleFiles += self.styleDir.files("*.gif")
        styleFiles += self.styleDir.files("*.png")
        styleFiles += self.styleDir.files("*.js")
        styleFiles += self.styleDir.files("*.html")
        self.styleDir.copylist(styleFiles, outputDir)

        # copy the package's resource files
        package.resourceDir.copyfiles(outputDir)
            
        # Export the package content
        self.pages = [ IMSPage("index", 1, package.root) ]

        self.generatePages(package.root, 2)
        uniquifyNames(self.pages)

        for page in self.pages:
            page.save(outputDir)

        # Create the manifest file
        manifest = Manifest(self.config, outputDir, package, self.pages)
        manifest.save()
        
        # Copy the scripts - with modification by lernmodule.net
        self.scriptsDir.copylist(('libot_drag.js',
                                  'lernmodule_net.js',
                                  'common.js'), outputDir)
        
        self.schemasDir.copylist(('imscp_v1p1.xsd',
                                  'imsmd_v1p2p2.xsd',
                                  'ims_xml.xsd'), outputDir)
        
        # copy players for media idevices.                
        hasFlowplayer     = False
        hasMagnifier      = False
        hasXspfplayer     = False
        isBreak           = False
        
        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'magnifier.swf' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True
                        
        if hasFlowplayer:
            videofile = (self.templatesDir/'flowPlayer.swf')
            videofile.copyfile(outputDir/'flowPlayer.swf')
        if hasMagnifier:
            videofile = (self.templatesDir/'magnifier.swf')
            videofile.copyfile(outputDir/'magnifier.swf')
        if hasXspfplayer:
            videofile = (self.templatesDir/'xspf_player.swf')
            videofile.copyfile(outputDir/'xspf_player.swf')

        if package.license == "GNU Free Documentation License":
            # include a copy of the GNU Free Documentation Licence
            (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html')
        # Zip it up!
        self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir)
        # Clean up the temporary dir
        outputDir.rmtree()

    def doZip(self, fileObj, outputDir):
        """
        Actually does the zipping of the file. Called by 'Path.safeSave'
        """
        zipped = ZipFile(fileObj, "w")
        for scormFile in outputDir.files():
            zipped.write(scormFile,
                    scormFile.basename().encode('utf8'), ZIP_DEFLATED)
        zipped.close()

    def generatePages(self, node, depth):
        """
        Recursive function for exporting a node.
        'outputDir' is the temporary directory that we are exporting to
        before creating zip file
        """
        for child in node.children:
            pageName = child.titleShort.lower().replace(" ", "_")
            pageName = re.sub(r"\W", "", pageName)
            if not pageName:
                pageName = "__"

            page = IMSPage(pageName, depth, child)

            self.pages.append(page)
            self.generatePages(child, depth + 1)
Beispiel #39
0
#!/usr/bin/python

# setup.py
from setuptools import setup
from exe.engine import version
from exe.engine.path import Path

# Before we install, make sure all the mimetex binaries are executable
Path('exe/webui/templates/mimetex.cgi').chmod(0755)
Path('exe/webui/templates/mimetex.64.cgi').chmod(0755)

files = {
    '/usr/share/exe':
    ["README", "COPYING", "NEWS", "ChangeLog", "exe/webui/mr_x.gif"],
    '/usr/share/applications': ["exe.desktop"],
    '/usr/share/icons/hicolor/48x48/apps': ["exe.png"],
}


def dataFiles(baseSourceDir, baseDestDir, sourceDirs):
    """Recursively get all the files in these directories"""
    global files
    from exe.engine.path import Path
    baseSourceDir = Path(baseSourceDir)
    baseDestDir = Path(baseDestDir)
    sourceDirs = map(Path, sourceDirs)
    for sourceDir in sourceDirs:
        sourceDir = baseSourceDir / sourceDir
        for subDir in list(sourceDir.walkdirs()) + [sourceDir]:
            if set(
                ('CVS', '.svn', 'tinymce_3.5.4.1')) & set(subDir.splitall()):
Beispiel #40
0
    def renderEdit(self, style):
        """
        Returns an XHTML string with the form element for editing this block
        """
        html = u'<div>'
        html += '<span class="js-idevice-title-label">'
        html += '<label for="title'+self.id+'">'+_('Title')+':</label> '
        html += common.elementInstruc(_('The title and the icon are not required. If you leave them empty the iDevice will have no emphasis.'))
        html += '</span>'
        html += common.hiddenField("iconiDevice" + self.id, self.idevice.icon)
        html += u'<a class="js-show-icon-panel-button" href="javascript:showMessageBox(\'iconpanel\');" title="%s"><img src="/images/stock-insert-image.png" alt="%s" width="16" height="16" /></a>' % (_('Select an icon'),_('Choose an Image'))        
        
        # Get icon source (if it exists)
        icon = self.idevice.icon
        icon_exists = False
        if icon != '':
            idevice_icon = Path(G.application.config.stylesDir / style / 'icon_' + self.idevice.icon + '.gif')
            if idevice_icon.exists():
                icon_exists = True
            else:
                idevice_icon = Path(G.application.config.stylesDir/style/"icon_" + self.idevice.icon + ".png")
                if idevice_icon.exists():
                    icon_exists = True
                else:
                    idevice_icon = Path(G.application.config.stylesDir/style/"icon_" + self.idevice.icon + ".svg")
                    if idevice_icon.exists():
                        icon_exists = True

        # Icon HTML element
        html += u'<img class="js-idevide-icon-preview" name="iconiDevice%s" id="iconiDevice"' % (self.id)
        if icon_exists:
            html += u' src="/style/%s/icon_%s%s"' % (style, icon, idevice_icon.ext)
        else:
            html += u' src="/images/empty.gif"'
        html += u'/>'

        # Delete button
        html += u'<a href="javascript:deleteIcon(%s);" id="deleteIcon%s" class="deleteIcon" title="%s"' % (self.id, self.id, _('Delete'))
        # If the icon doesn't exists
        if not icon_exists:
            html += u' style="display: none;"'
        html += u'>'
        html += u'<img class="js-delete-icon" alt="%s" src="%s"/>' % (_('Delete'), '/images/stock-delete.png')
        html += u'</a>'
        
        html += common.textInput("title" + self.id, self.idevice.title)

        html += u'<div class="js-icon-panel-container">'
        html += u'<div id="iconpaneltitle">%s</div>' % _("Icons")
        html += u'<div id="iconpanelcontent">'
        html += self.__renderIcons(style)
        html += u'</div>'
        
        html += u"</div>"

        for element in self.elements:
            html += element.renderEdit()

        html += self.renderEditButtons()
        html += u"</div>"

        return html
Beispiel #41
0
class WebsiteExport(object):
    """
    WebsiteExport will export a package as a website of HTML pages
    """
    def __init__(self, config, styleDir, filename, prefix=""):
        """
        'stylesDir' is the directory where we can copy the stylesheets from
        'outputDir' is the directory that will be [over]written
        with the website
        """
        self.config = config
        self.imagesDir = config.webDir / "images"
        self.scriptsDir = config.webDir / "scripts"
        self.templatesDir = config.webDir / "templates"
        self.stylesDir = Path(styleDir)
        self.filename = Path(filename)
        self.pages = []
        self.prefix = prefix

    def exportZip(self, package):
        """ 
        Export web site
        Cleans up the previous packages pages and performs the export
        """

        outputDir = TempDirPath()

        # Import the Website Page class.  If the style has it's own page class
        # use that, else use the default one.
        if (self.stylesDir / "websitepage.py").exists():
            global WebsitePage
            module = imp.load_source("websitepage",
                                     self.stylesDir / "websitepage.py")
            WebsitePage = module.WebsitePage

        self.pages = [WebsitePage("index", 1, package.root)]
        self.generatePages(package.root, 1)
        uniquifyNames(self.pages)

        prevPage = None
        thisPage = self.pages[0]

        for nextPage in self.pages[1:]:
            thisPage.save(outputDir, prevPage, nextPage, self.pages)
            prevPage = thisPage
            thisPage = nextPage

        thisPage.save(outputDir, prevPage, None, self.pages)
        self.copyFiles(package, outputDir)
        # Zip up the website package
        self.filename.safeSave(
            self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'),
            outputDir)
        # Clean up the temporary dir
        outputDir.rmtree()

    def doZip(self, fileObj, outputDir):
        """
        Actually saves the zip data. Called by 'Path.safeSave'
        """
        zipped = ZipFile(fileObj, "w")
        for scormFile in outputDir.files():
            zipped.write(scormFile,
                         scormFile.basename().encode('utf8'), ZIP_DEFLATED)
        zipped.close()

    def export(self, package):
        """ 
        Export web site
        Cleans up the previous packages pages and performs the export
        """
        outputDir = self.filename
        if not outputDir.exists():
            outputDir.mkdir()

        # Import the Website Page class.  If the style has it's own page class
        # use that, else use the default one.
        if (self.stylesDir / "websitepage.py").exists():
            global WebsitePage
            module = imp.load_source("websitepage",
                                     self.stylesDir / "websitepage.py")
            WebsitePage = module.WebsitePage

        self.pages = [WebsitePage(self.prefix + "index", 1, package.root)]
        self.generatePages(package.root, 1)
        uniquifyNames(self.pages)

        prevPage = None
        thisPage = self.pages[0]

        for nextPage in self.pages[1:]:
            thisPage.save(outputDir, prevPage, nextPage, self.pages)
            prevPage = thisPage
            thisPage = nextPage

        thisPage.save(outputDir, prevPage, None, self.pages)

        if self.prefix == "":
            self.copyFiles(package, outputDir)

    def copyFiles(self, package, outputDir):
        """
        Copy all the files used by the website.
        """
        # Copy the style sheet files to the output dir
        styleFiles = [self.stylesDir / '..' / 'base.css']
        styleFiles += [self.stylesDir / '..' / 'popup_bg.gif']
        styleFiles += self.stylesDir.files("*.css")
        styleFiles += self.stylesDir.files("*.jpg")
        styleFiles += self.stylesDir.files("*.gif")
        styleFiles += self.stylesDir.files("*.png")
        styleFiles += self.stylesDir.files("*.js")
        styleFiles += self.stylesDir.files("*.html")
        styleFiles += self.stylesDir.files("*.ico")
        self.stylesDir.copylist(styleFiles, outputDir)

        # copy the package's resource files
        package.resourceDir.copyfiles(outputDir)

        # copy script files.
        self.scriptsDir.copylist(('libot_drag.js', 'common.js'), outputDir)

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        isBreak = False

        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'magnifier.swf' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(outputDir / 'flowPlayer.swf')
# JR: anadimos los controles
        controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
        controlsfile.copyfile(outputDir / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'magnifier.swf')
            videofile.copyfile(outputDir / 'magnifier.swf')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(outputDir / 'xspf_player.swf')

        if package.license == "GNU Free Documentation License":
            # include a copy of the GNU Free Documentation Licence
            (self.templatesDir / 'fdl.html').copyfile(outputDir / 'fdl.html')

    def generatePages(self, node, depth):
        """
        Recursively generate pages and store in pages member variable
        for retrieving later
        """
        for child in node.children:
            pageName = child.titleShort.lower().replace(" ", "_")
            pageName = re.sub(r"\W", "", pageName)
            if not pageName:
                pageName = "__"

            self.pages.append(WebsitePage(self.prefix + pageName, depth,
                                          child))
            self.generatePages(child, depth + 1)
Beispiel #42
0
class Config(object):
    """
    The Config class contains the configuration information for eXe.
    """

    # To build link to git revision
    baseGitWebURL = 'https://github.com/exelearning/iteexe'

    # Class attributes
    optionNames = {
        'system':
        ('webDir', 'jsDir', 'port', 'dataDir', 'configDir', 'localeDir',
         'stylesRepository', 'browser', 'mediaProfilePath',
         'videoMediaConverter_ogv', 'videoMediaConverter_3gp',
         'videoMediaConverter_mpg', 'videoMediaConverter_avi',
         'audioMediaConverter_ogg', 'audioMediaConverter_au',
         'audioMediaConverter_mp3', 'audioMediaConverter_wav', 'ffmpegPath'),
        'user':
        ('locale', 'lastDir', 'showPreferencesOnStart',
         'showNewVersionWarningOnStart', 'defaultStyle', 'eXeUIversion',
         'showIdevicesGrouped', 'docType', 'editorMode', 'editorVersion',
         'defaultLicense', 'forceEditableExport', 'cutFileName',
         'autosaveTime', 'metadataWarning'),
    }

    idevicesCategories = {
        # Use Experimental for complex non-tested iDevices and Hidden for those that should not be added any more
        'activity': [x_('Text and Tasks')],
        'reading activity': [x_('Text and Tasks')],
        'dropdown activity': [x_('Interactive Activities')],
        'java applet': [x_('Interactive Activities')],
        'wiki article': [x_('Other Contents')],
        'case study': [x_('Text and Tasks')],
        'preknowledge': [x_('Text and Tasks')],
        'scorm quiz': [x_('Interactive Activities')],
        'fpd - multi choice activity': [x_('FPD')],
        'fpd - cloze activity': [x_('FPD')],
        'fpd - cloze activity (modified)': [x_('FPD')],
        'fpd - multi select activity': [x_('FPD')],
        'fpd - true/false activity': [x_('FPD')],
        'fpd - situation': [x_('FPD')],
        'fpd - quotation': [x_('FPD')],
        'fpd - you should know': [x_('FPD')],
        'fpd - highlighted': [x_('FPD')],
        'fpd - translation': [x_('FPD')],
        'fpd - guidelines students': [x_('FPD')],
        'fpd - guidelines teacher': [x_('FPD')],
        'fpd - a step ahead': [x_('FPD')],
        'fpd - a piece of advice': [x_('FPD')],
        'fpd - think about it (with feedback)': [x_('FPD')],
        'fpd - think about it (without feedback)': [x_('FPD')],
        'fpd - free text': [x_('FPD')],
        'image gallery': [x_('Other Contents')],
        'image magnifier': [x_('Other Contents')],
        'note': [x_('Other Contents')],
        'objectives': [x_('Text and Tasks')],
        'multi-choice': [x_('Interactive Activities')],
        'multi-select': [x_('Interactive Activities')],
        'true-false question': [x_('Interactive Activities')],
        'reflection': [x_('Text and Tasks')],
        'cloze activity': [x_('Interactive Activities')],
        'rss': [x_('Other Contents')],
        'external web site': [x_('Other Contents')],
        'free text': [x_('Text and Tasks')],
        'click in order game': [x_('Hidden')],
        'hangman game': [x_('Hidden')],
        'place the objects': [x_('Interactive Activities')],
        'memory match game': [x_('Hidden')],
        'file attachments': [x_('Other Contents')],
        'sort items': [x_('Hidden')]
    }

    @classmethod
    def getConfigPath(cls):
        obj = cls.__new__(cls)
        obj.configParser = ConfigParser()
        obj._overrideDefaultVals()
        obj.__setConfigPath()
        return obj.configPath

    def __init__(self):
        """
        Initialise
        """
        self.configPath = None
        self.configParser = ConfigParser(self.onWrite)
        # Set default values
        # exePath is the whole path and filename of the exe executable
        self.exePath = Path(sys.argv[0]).abspath()
        # webDir is the parent directory for styles,scripts and templates
        self.webDir = self.exePath.dirname()
        self.jsDir = self.exePath.dirname()
        self.locales = {}
        # localeDir is the base directory where all the locales are stored
        self.localeDir = self.exePath.dirname() / "locale"
        # port is the port the exe webserver will listen on
        # (previous default, which earlier users might still use, was 8081)
        self.port = 51235
        # dataDir is the default directory that is shown to the user
        # to save packages and exports in
        self.dataDir = Path(".")
        # configDir is the dir for storing user profiles
        # and user made idevices and the config file
        self.configDir = Path(".")
        # FM: New Styles Directory path
        self.stylesDir = Path(self.configDir / 'style').abspath()
        # FM: Default Style name
        self.defaultStyle = u"INTEF"
        # Styles repository XML-RPC endpoint
        # self.stylesRepository = 'http://www.exelearning.es/xmlrpc.php'
        self.stylesRepository = 'http://www.exelearning.net/xmlrpc.php'
        # browser is the name of a predefined browser specified
        # at http://docs.python.org/library/webbrowser.html.
        # None for system default
        self.browser = None
        # docType  is the HTML export format
        self.docType = 'HTML5'
        # internalAnchors indicate which exe_tmp_anchor tags to generate for each tinyMCE field
        # available values = "enable_all", "disable_autotop", or "disable_all"
        self.internalAnchors = "enable_all"
        self.lastDir = None
        self.showPreferencesOnStart = "1"
        self.showNewVersionWarningOnStart = "1"
        self.showIdevicesGrouped = "1"
        # tinymce option
        self.editorMode = 'permissive'
        self.editorVersion = '4'
        # styleSecureMode : if this [user] key is = 0  , exelearning can run python files in styles
        # as websitepage.py , ... ( deactivate secure mode )
        self.styleSecureMode = "1"
        # styles is the list of style names available for loading
        self.styles = []
        # The documents that we've recently looked at
        self.recentProjects = []
        # canonical (English) names of iDevices not to show in the iDevice pane
        self.hiddeniDevices = []
        # Media conversion programs used for XML export system
        self.videoMediaConverter_ogv = ""
        self.videoMediaConverter_3gp = ""
        self.videoMediaConverter_avi = ""
        self.videoMediaConverter_mpg = ""
        self.audioMediaConverter_ogg = ""
        self.audioMediaConverter_au = ""
        self.audioMediaConverter_mp3 = ""
        self.audioMediaConverter_wav = ""
        self.ffmpegPath = ""
        self.mediaProfilePath = self.exePath.dirname() / 'mediaprofiles'

        # likewise, a canonical (English) names of iDevices not to show in the
        # iDevice pane but, contrary to the hiddens, these are ones that the
        # configuration can specify to turn ON:
        self.deprecatediDevices = [
            "flash with text", "flash movie", "mp3", "attachment"
        ]
        # by default, only allow embedding of media types for which a
        # browser plugin is found:

        self.defaultLicense = 'creative commons: attribution - share alike 4.0'

        self.assumeMediaPlugins = False

        # Force the editable export when loading an existing
        # package with it disabled (defaults to disabled)
        self.forceEditableExport = "0"

        # Content templates directory
        self.templatesDir = Path(self.configDir / 'content_template').abspath()
        # Default template that will be used to all new content
        self.defaultContentTemplate = "Base"

        # JS Idevices directory
        self.jsIdevicesDir = Path(self.configDir / 'scripts' /
                                  'idevices').abspath()

        # Let our children override our defaults depending
        # on the OS that we're running on
        self._overrideDefaultVals()
        # locale is the language of the user. localeDir can be overridden
        # that's why we must set it _after_ the call to _overrideDefaultVals()
        self.locale = chooseDefaultLocale(self.localeDir)

        # Format the files and images to standard ISO 9660
        self.cutFileName = "0"

        self.autosaveTime = "10"

        self.metadataWarning = "1"

        # Try to make the defaults a little intelligent
        # Under devel trees, webui is the default webdir
        self.webDir = Path(self.webDir)
        if not (self.webDir/'scripts').isdir() \
           and (self.webDir/'webui').isdir():
            self.webDir /= 'webui'
        self.jsDir = Path(self.jsDir)
        if not (self.jsDir/'scripts').isdir() \
           and (self.jsDir/'jsui').isdir():
            self.jsDir /= 'jsui'
        # Find where the config file will be saved
        self.__setConfigPath()
        # Fill in any undefined config options with our defaults
        self._writeDefaultConfigFile()
        # Now we are ready to serve the application
        self.loadSettings()
        self.setupLogging()
        self.loadLocales()
        self.loadStyles()
        self.loadTemplates()

    def _overrideDefaultVals(self):
        """
        Override this to override the
        default config values
        """

    def _getConfigPathOptions(self):
        """
        Override this to give a list of
        possible config filenames
        in order of preference
        """
        return ['exe.conf']

    def _writeDefaultConfigFile(self):
        """
        [Over]writes 'self.configPath' with a default config file
        (auto write is on so we don't need to write the file at the end)
        """
        if not G.application.portable:
            for sectionName, optionNames in self.optionNames.items():
                for optionName in optionNames:
                    defaultVal = getattr(self, optionName)
                    self.configParser.setdefault(sectionName, optionName,
                                                 defaultVal)
            # Logging can't really be changed from inside the program at the moment...
            self.configParser.setdefault('logging', 'root', 'INFO')

    def __setConfigPath(self):
        """
        sets self.configPath to the filename of the config file that we'll
        use.
        In descendant classes set self.configFileOptions to a list
        of directories where the configDir should be in order of preference.
        If no config files can be found in these dirs, it will
        force creation of the config file in the top dir
        """
        # If there's an EXECONF environment variable, use it
        self.configPath = None
        configFileOptions = map(Path, self._getConfigPathOptions())
        if "EXECONF" in os.environ:
            envconf = Path(os.environ["EXECONF"])
            if envconf.isfile():
                self.configPath = os.environ["EXECONF"]
        # Otherwise find the most appropriate existing file
        if self.configPath is None:
            for confPath in configFileOptions:
                if confPath.isfile():
                    self.configPath = confPath
                    break
            else:
                # If no config files exist, create and use the
                # first one on the list
                self.configPath = configFileOptions[0]
                folder = self.configPath.abspath().dirname()
                if not folder.exists():
                    folder.makedirs()
                self.configPath.touch()
        # Now make our configParser
        self.configParser.read(self.configPath)
        self.configParser.autoWrite = True

    def upgradeFile(self):
        """
        Called before loading the config file,
        removes or upgrades any old settings.
        """
        if self.configParser.has_section('system'):
            system = self.configParser.system
            if system.has_option('appDataDir'):
                # Older config files had configDir stored as appDataDir
                self.configDir = Path(system.appDataDir)
                self.stylesDir = Path(self.configDir) / 'style'
                self.templatesDir = Path(self.configDir) / 'content_template'
                self.jsIdevicesDir = Path(
                    self.configDir) / 'scripts' / 'idevices'
                # We'll just upgrade their config file for them for now...
                system.configDir = self.configDir
                system.stylesDir = Path(self.configDir) / 'style'
                system.templatesDir = Path(self.configDir) / 'content_template'
                system.jsIdevicesDir = Path(
                    self.configDir) / 'scripts' / 'idevices'
                del system.appDataDir

                self.audioMediaConverter_au = system.audioMediaConverter_au
                self.audioMediaConverter_wav = system.audioMediaConverter_wav
                self.videoMediaConverter_ogv = system.videoMediaConverter_ogv
                self.videoMediaConverter_3gp = system.videoMediaConverter_3gp
                self.videoMediaConverter_avi = system.videoMediaConverter_avi
                self.videoMediaConverter_mpg = system.videoMediaConverter_mpg
                self.audioMediaConverter_ogg = system.audioMediaConverter_ogg
                self.audioMediaConverter_mp3 = system.audioMediaConverter_mp3
                self.ffmpegPath = system.ffmpegPath

            self.mediaProfilePath = system.mediaProfilePath

            if system.has_option('greDir'):
                # No longer used, system should automatically support
                del system.greDir
            if system.has_option('xulDir'):
                del system.xulDir
            # if system.has_option('browser'):
            #    del system.browser

    def loadSettings(self):
        """
        Loads the settings from the exe.conf file.
        Overrides the defaults set in __init__
        """

        # Set up the parser so that if a certain value is not in the config
        # file, it will use the value from our default values
        def defVal(dummy, option):
            """If something is not in the config file, just use the default in
            'self'"""
            return getattr(self, option)

        self.configParser.defaultValue = defVal
        self.upgradeFile()
        # System Section
        if self.configParser.has_section('system'):
            system = self.configParser.system

            self.port = int(system.port)
            self.browser = None if system.browser == u"None" else system.browser
            self.stylesRepository = system.stylesRepository

            if not G.application.portable:
                self.dataDir = Path(system.dataDir)
                self.configDir = Path(system.configDir)
                self.webDir = Path(system.webDir)
                self.stylesDir = Path(self.configDir) / 'style'
                self.templatesDir = Path(self.configDir) / 'content_template'
                self.jsIdevicesDir = Path(
                    self.configDir) / 'scripts' / 'idevices'
                self.jsDir = Path(system.jsDir)
            else:
                self.stylesDir = Path(self.webDir / 'style').abspath()
                self.templatesDir = Path(self.webDir /
                                         'content_template').abspath()
                self.jsIdevicesDir = Path(self.webDir / 'scripts' /
                                          'idevices').abspath()

            self.assumeMediaPlugins = False
            if self.configParser.has_option('system', 'assumeMediaPlugins'):
                value = system.assumeMediaPlugins.strip().lower()
                if value == "1" or value == "yes" or value == "true" or value == "on":
                    self.assumeMediaPlugins = True

        # If the dataDir points to some other dir, fix it
        if not self.dataDir.isdir():
            self.dataDir = tempfile.gettempdir()
        # make the webDir absolute, to hide path joins of relative paths
        self.webDir = self.webDir.expand().abspath()
        # If the configDir doesn't exist (as it may be a default setting with a
        # new installation) create it
        if not self.configDir.exists():
            self.configDir.mkdir()

        if not G.application.standalone:
            # FM: Copy styles
            if not os.path.exists(self.stylesDir) or not os.listdir(
                    self.stylesDir):
                self.copyStyles()
            else:
                self.updateStyles()

            # Copy templates
            if not os.path.exists(self.templatesDir) or not os.listdir(
                    self.templatesDir):
                self.copyTemplates()
            else:
                self.updateTemplates()

            # Copy JavaScript Idevices
            if not os.path.exists(self.jsIdevicesDir) or not os.listdir(
                    self.jsIdevicesDir):
                self.copy_js_idevices()
            else:
                self.update_js_idevices()
        else:
            if G.application.portable:
                if os.name == 'posix':
                    self.stylesDir = Path(self.webDir / '..' / '..' / '..' /
                                          'style')
                    self.templatesDir = Path(self.webDir / '..' / '..' / '..' /
                                             'content_template')
                    self.jsIdevicesDir = Path(self.webDir / '..' / '..' /
                                              '..' / 'scripts' / 'idevices')

                else:
                    self.stylesDir = Path(self.webDir / '..' / 'style')
                    self.templatesDir = Path(self.webDir / '..' /
                                             'content_template')
                    self.jsIdevicesDir = Path(self.webDir / '..' / 'scripts' /
                                              'idevices')

                if not os.path.exists(self.stylesDir) or not os.listdir(
                        self.stylesDir):
                    self.copyStyles()

                if not os.path.exists(self.templatesDir) or not os.listdir(
                        self.templatesDir):
                    self.copyTemplates()

                if not os.path.exists(self.jsIdevicesDir) or not os.listdir(
                        self.jsIdevicesDir):
                    self.copy_js_idevices()
            else:
                self.stylesDir = Path(self.webDir / 'style').abspath()
                self.templatesDir = Path(self.webDir /
                                         'content_template').abspath()
                self.jsIdevicesDir = Path(self.webDir / 'scripts' /
                                          'idevices').abspath()

        # Get the list of recently opened projects
        self.recentProjects = []
        if self.configParser.has_section('recent_projects'):
            recentProjectsSection = self.configParser.recent_projects
            # recentProjectsSection.items() is in the wrong order, keys are alright.
            # Sorting list by key before adding to self.recentProjects, to avoid wrong ordering
            # in Recent Projects menu list
            recentProjectsItems = recentProjectsSection.items()
            recentProjectsItems.sort()
            for key, path in recentProjectsItems:
                self.recentProjects.append(path)

        # Load the list of "hidden" iDevices
        self.hiddeniDevices = []
        if self.configParser.has_section('idevices'):
            idevicesSection = self.configParser.idevices
            for key, value in idevicesSection.items():
                # emulate standard library's getboolean()
                value = value.strip().lower()
                if value == "0" or value == "no" or value == "false" or \
                        value == "off":
                    self.hiddeniDevices.append(key.lower())

        # self.deprecatediDevices = [ "flash with text", "flash movie", ...]
        # and UN-Load from the list of "deprecated" iDevices
        if self.configParser.has_section('deprecated'):
            deprecatedSection = self.configParser.deprecated
            for key, value in deprecatedSection.items():
                # emulate standard library's getboolean()
                value = value.strip().lower()
                if value == "1" or value == "yes" or value == "true" or \
                        value == "on":
                    if key.lower() in self.deprecatediDevices:
                        self.deprecatediDevices.remove(key.lower())

        # Load the "user" section
        if self.configParser.has_section('user'):
            if self.configParser.user.has_option('editorMode'):
                self.editorMode = self.configParser.user.editorMode
            if self.configParser.user.has_option('editorVersion'):
                self.editorVersion = self.configParser.user.editorVersion
            if self.configParser.user.has_option('docType'):
                self.docType = self.configParser.user.docType
                common.setExportDocType(self.configParser.user.docType)
            if self.configParser.user.has_option('defaultStyle'):
                self.defaultStyle = self.configParser.user.defaultStyle
            if self.configParser.user.has_option('styleSecureMode'):
                self.styleSecureMode = self.configParser.user.styleSecureMode
            if self.configParser.user.has_option('internalAnchors'):
                self.internalAnchors = self.configParser.user.internalAnchors
            if self.configParser.user.has_option('lastDir'):
                self.lastDir = self.configParser.user.lastDir
            if self.configParser.user.has_option('showPreferencesOnStart'):
                self.showPreferencesOnStart = self.configParser.user.showPreferencesOnStart
            if self.configParser.user.has_option(
                    'showNewVersionWarningOnStart'):
                self.showNewVersionWarningOnStart = self.configParser.user.showNewVersionWarningOnStart
            if self.configParser.user.has_option('showIdevicesGrouped'):
                self.showIdevicesGrouped = self.configParser.user.showIdevicesGrouped
            if self.configParser.user.has_option('locale'):
                self.locale = self.configParser.user.locale
            if self.configParser.user.has_option('defaultLicense'):
                self.defaultLicense = self.configParser.user.defaultLicense
            if self.configParser.user.has_option('forceEditableExport'):
                self.forceEditableExport = self.configParser.user.forceEditableExport
            if self.configParser.user.has_option('cutFileName'):
                self.cutFileName = self.configParser.user.cutFileName
            if self.configParser.user.has_option('autosaveTime'):
                self.autosaveTime = self.configParser.user.autosaveTime
            if self.configParser.user.has_option('metadataWarning'):
                self.metadataWarning = self.configParser.user.metadataWarning

    def onWrite(self, configParser):
        """
        Called just before the config file is written.
        We use it to fill out any settings that are stored here and
        not in the config parser itself
        """
        # Recent projects
        self.configParser.delete('recent_projects')
        recentProjectsSection = self.configParser.addSection('recent_projects')
        for num, path in enumerate(self.recentProjects):
            recentProjectsSection[str(num)] = path

    def setupLogging(self):
        """
        setup logging file
        """
        try:
            hdlr = RotatingFileHandler(self.configDir / 'exe.log', 'a', 500000,
                                       10)
            hdlr.doRollover()
        except OSError:
            # ignore the error we get if the log file is logged
            hdlr = logging.FileHandler(self.configDir / 'exe.log')

        format = "%(asctime)s %(name)s %(levelname)s %(message)s"
        log = logging.getLogger()
        hdlr.setFormatter(logging.Formatter(format))
        log.addHandler(hdlr)

        loggingLevels = {
            "DEBUG": logging.DEBUG,
            "INFO": logging.INFO,
            "WARNING": logging.WARNING,
            "ERROR": logging.ERROR,
            "CRITICAL": logging.CRITICAL
        }

        if self.configParser.has_section('logging'):
            for logger, level in self.configParser._sections["logging"].items(
            ):
                if logger == "root":
                    logging.getLogger().setLevel(loggingLevels[level])
                else:
                    logging.getLogger(logger).setLevel(loggingLevels[level])
        if not G.application.portable:
            log.info("************** eXe logging started **************")
            log.info("version     = %s" % version.version)
            log.info("configPath  = %s" % self.configPath)
            log.info("exePath     = %s" % self.exePath)
            log.info("libPath     = %s" %
                     Path(twisted.__path__[0]).splitpath()[0])
            log.info("browser     = %s" % self.browser)
            log.info("webDir      = %s" % self.webDir)
            log.info("jsDir       = %s" % self.jsDir)
            log.info("localeDir   = %s" % self.localeDir)
            log.info("port        = %d" % self.port)
            log.info("dataDir     = %s" % self.dataDir)
            log.info("configDir   = %s" % self.configDir)
            log.info("locale      = %s" % self.locale)
            log.info("internalAnchors = %s" % self.internalAnchors)
            log.info("License = %s" % self.defaultLicense)

    def loadStyles(self):
        """
        Scans the eXe style directory and builds a list of styles
        """
        self.styleStore = StyleStore(self)
        listStyles = self.styleStore.getStyles()
        for style in listStyles:
            self.styles.append(style)
            # print style

    def loadTemplates(self):
        """
        Scans the eXe templates directory and builds a list of templates
        """
        self.templateStore = TemplateStore(self)
        self.templateStore.load()

    def copyStyles(self):
        bkstyle = self.webDir / 'style'
        dststyle = self.stylesDir
        if os.path.exists(bkstyle):
            if os.path.exists(dststyle) and not os.listdir(self.stylesDir):
                shutil.rmtree(dststyle)
            shutil.copytree(bkstyle, dststyle)

    def updateStyles(self):
        bkstyle = self.webDir / 'style'
        dststyle = self.stylesDir
        if os.stat(bkstyle).st_mtime - os.stat(dststyle).st_mtime > 1:
            for name in os.listdir(bkstyle):
                bksdirstyle = os.path.join(bkstyle, name)
                dstdirstyle = os.path.join(dststyle, name)
                if os.path.isdir(bksdirstyle):
                    if os.path.exists(dstdirstyle):
                        shutil.rmtree(dstdirstyle)
                    shutil.copytree(bksdirstyle, dstdirstyle)
                else:
                    shutil.copy(bksdirstyle, dstdirstyle)

    def copyTemplates(self):
        template_backup = self.webDir / 'content_template'
        dest_template = self.templatesDir
        if os.path.exists(template_backup):
            if os.path.exists(dest_template) and not os.listdir(
                    self.dest_template):
                shutil.rmtree(dest_template)
            shutil.copytree(template_backup, dest_template)

    def updateTemplates(self):
        template_backup = self.webDir / 'content_template'
        dest_template = self.templatesDir
        if os.stat(template_backup).st_mtime - os.stat(
                dest_template).st_mtime > 1:
            for name in os.listdir(template_backup):
                current_template = os.path.join(template_backup, name)
                current_dest_template = os.path.join(dest_template, name)
                if os.path.isdir(current_template):
                    if os.path.exists(current_dest_template):
                        shutil.rmtree(current_dest_template)
                    shutil.copytree(current_template, current_dest_template)
                else:
                    shutil.copy(current_template, current_dest_template)

    def copy_js_idevices(self):
        """
        Copies the default JS Idevices to the configuration folder.
        It's usually only executed the first time eXe is installed or the
        moment the user updates to the first version that used them.

        :rtype: void
        """
        # Get the path where the JsIdevices are
        jsidevices_backup = self.webDir / 'scripts' / 'idevices'

        # Check if the path exists (if it doesn't there is nothing to be done)
        if os.path.exists(jsidevices_backup):
            # Remove the user's JsIdevices directory in case it exists
            if os.path.exists(
                    self.jsIdevicesDir) and not os.listdir(self.jsIdevicesDir):
                shutil.rmtree(self.jsIdevicesDir)

            # Copy the JsIdevices
            shutil.copytree(jsidevices_backup, self.jsIdevicesDir)

    def update_js_idevices(self):
        """
        Update JS Idevices from the ones that come with eXe.
        This will be done everytime eXe is started, so in case
        any JsIdevice is updated it will automatically update the first
        time the user opens eXe.

        :rtype: void
        """
        # Get the path where the JsIdevices are
        jsidevices_backup = self.webDir / 'scripts' / 'idevices'

        # Compare the directories' modification time to see if the update is necessary
        if os.stat(jsidevices_backup).st_mtime - os.stat(
                self.jsIdevicesDir).st_mtime > 1:
            # Go through all JsIdevices
            for name in os.listdir(jsidevices_backup):
                # Copy the Idevice
                current_idevice = os.path.join(jsidevices_backup, name)
                current_dest_idevice = os.path.join(self.jsIdevicesDir, name)

                # This shouldn't really be necessary, but we keep it as
                # it would copy the exact structure of the 'idevices' folder.
                if os.path.isdir(current_idevice):
                    if os.path.exists(current_dest_idevice):
                        shutil.rmtree(current_dest_idevice)
                    shutil.copytree(current_idevice, current_dest_idevice)
                else:
                    shutil.copy(current_idevice, current_dest_idevice)

    def loadLocales(self):
        """
        Scans the eXe locale directory and builds a list of locales
        """
        log = logging.getLogger()
        log.debug("loadLocales")
        gettext.install('exe', self.localeDir, True)
        for subDir in self.localeDir.dirs():
            if (subDir / 'LC_MESSAGES' / 'exe.mo').exists():
                self.locales[subDir.basename()] = \
                    gettext.translation('exe',
                                        self.localeDir,
                                        languages=[str(subDir.basename())])
        if self.locale not in self.locales:
            self.locale = 'en'
        log.debug("loading locale %s" % self.locale)
        self.locales[self.locale].install(unicode=True)
        __builtins__['c_'] = lambda s: self.locales[self.locale].ugettext(
            s) if s else s
Beispiel #43
0
    def render_POST(self, request):
        """
        function replaced by nevow_clientToServerEvent to avoid POST message
        """
        log.debug("render_POST " + repr(request.args))
        data = {}
        try:
            locale = request.args['locale'][0]
            self.config.locale = locale
            self.config.locales[locale].install(unicode=True)
            self.config.configParser.set('user', 'locale', locale)

            internalAnchors = request.args['internalAnchors'][0]
            self.config.internalAnchors = internalAnchors
            self.config.configParser.set('user', 'internalAnchors',
                                         internalAnchors)

            editormodesel = request.args['editorMode'][0]
            self.config.editorMode = editormodesel
            self.config.configParser.set('user', 'editorMode', editormodesel)

            editorveresel = request.args['editorVersion'][0]
            self.config.editorVersion = editorveresel
            self.config.configParser.set('user', 'editorVersion',
                                         editorveresel)

            doctypesel = request.args['docType'][0]
            self.config.docType = doctypesel
            self.config.configParser.set('user', 'docType', doctypesel)

            defaultLicense = request.args['defaultLicense'][0]
            self.config.defaultLicense = defaultLicense
            self.config.configParser.set('user', 'defaultLicense',
                                         defaultLicense)

            forceEditableExport = request.args['forceEditableExport'][0]
            self.config.forceEditableExport = forceEditableExport
            self.config.configParser.set('user', 'forceEditableExport',
                                         forceEditableExport)

            browser = request.args['browser'][0]
            if browser == "None":
                browser = None
            try:
                self.config.browser = mywebbrowser.get(browser)
            except Exception as e:
                browser_path = Path(browser)
                if browser_path.exists():
                    mywebbrowser.register(
                        'custom-browser', None,
                        mywebbrowser.BackgroundBrowser(browser_path.abspath()),
                        -1)
                    self.config.browser = mywebbrowser.get('custom-browser')
                else:
                    raise e
            self.config.configParser.set('system', 'browser', browser)

            showPreferencesOnStart = request.args['showPreferencesOnStart'][0]
            self.config.showPreferencesOnStart = showPreferencesOnStart
            self.config.configParser.set('user', 'showPreferencesOnStart',
                                         showPreferencesOnStart)
        except Exception as e:
            log.exception(e)
            return json.dumps({
                'success': False,
                'errorMessage': _("Failed to save preferences")
            })
        return json.dumps({'success': True, 'data': data})
    def renameForMerging(self, newPackage):
        """
        to help the merging code in twisted/persisted/styles.py
        when it finds that this resource's storageName is already 
        in use with the merging destination package, newPackage.
        Finds a new unique name by prepending "m1_", "m2_", etc...
        note: new name should, of course, be unique to both the resource's
        current source package, as well as the destinateion newPackage.
        """ 
        old_name = self._storageName
        found_new_name = False
        new_name_attempt = 0
        preMergePackage = self.package

        # make sure that this possibly old resource HAS a proper checksum:
        self.checksumCheck()

        if self.checksum in newPackage.resources:
            # okay, this resource IS already in the newPackage,
            # but does it have the same name?
            if self._storageName  \
            == newPackage.resources[self.checksum][0]._storageName:
                # nothing else to do, so leave found_name_name as False:
                found_new_name = False
            else:
                # names differ!
                # ==> we need to rebuild the iDevice content from below,
                # but just set the new_name as that which is already
                # stored in the newPackage:
                new_name = newPackage.resources[self.checksum][0]._storageName
                found_new_name = True
            
        while not found_new_name: 
            # try prepending a merge suffix to the storageName, 
            # and see if that already exists in EITHER the src OR dst package.
            # try "m1_", or "m2_", etc...
            new_name_attempt += 1 
            new_name_suffix = "m" \
                + str(new_name_attempt) + "_"
            new_name = new_name_suffix \
                + self.storageName 

            if newPackage.findResourceByName(new_name) is None \
            and preMergePackage.findResourceByName(new_name) is None:
                found_new_name = True

        if found_new_name:
            log.warn("Renaming Resource from \""
                    + self.storageName + "\" to \""
                    + new_name)
            # rename the actual file, which is still located
            # in the preMergePackage temporary resourceDir:
            old_path = Path(preMergePackage.resourceDir)\
                    .joinpath(self.storageName) 
            new_path = Path(preMergePackage.resourceDir)\
                    .joinpath(new_name)
            newFullFileName = Path(old_path).rename(new_path)

            def updateIdevice(self):
                from exe.engine.appletidevice    import AppletIdevice
                from exe.engine.galleryidevice   import GalleryIdevice

                if isinstance(self._idevice, AppletIdevice):
                    # note that it COULD make it this far IF an AppletIdevice
                    # has the same resource, but by a different storageName, as
                    # another iDevice in the destination package:
                    raise Exception(_(u"renamed a Resource for an Applet Idevice, and it should not have even made it this far!"))

                elif isinstance(self._idevice, GalleryIdevice):
                    # Re-generate the GalleryIdevice popupHTML,
                    # but it's best to re-generate as an AfterUpgradeHandler,
                    # since its OTHER resources (some of which might themselves
                    # be renamed with the merge) might not have been updated yet!
                    if self._idevice._createHTMLPopupFile not in \
                    G.application.afterUpgradeHandlers:
                        G.application.afterUpgradeHandlers.append(
                            self._idevice._createHTMLPopupFile)

                else:
                    # if this is one of the many iDevices (generic or otherwise)
                    # which uses a FieldWithResources field, then the content
                    # will need to be changed directly.

                    this_field = self._idevice.getResourcesField(self)
                    from exe.engine.field            import FieldWithResources
                    if this_field is not None\
                    and isinstance(this_field, FieldWithResources):
                        # 1. just change .content_w_resourcePaths directly:
                        old_resource_path = "resources/" + old_name
                        new_resource_path = "resources/" + new_name
                        this_field.content_w_resourcePaths = \
                            this_field.content_w_resourcePaths.replace(
                                old_resource_path, new_resource_path)
                        # 2. copy .content_w_resourcePaths  directly into .content
                        # ONLY IF .content is already defined!
                        if hasattr(this_field, 'content'):
                            this_field.content = this_field.content_w_resourcePaths
                        # 3. re-create .content_wo_resourcePaths through Massage*()
                        # ONLY IF .content_wo_resourcePaths is already defined!
                        if hasattr(this_field, 'content_wo_resourcePaths'):
                            this_field.content_wo_resourcePaths = \
                                    this_field.MassageContentForRenderView()
                    else:
                        # Any other iDevice is assumed to simply have a direct
                        # link to the resource and need nothing else done.
                        # ==> nothing else to do, eh?
                        log.warn("Unaware of any other specific resource-renaming "
                                + "activities necessary for this type of idevice: "
                                + repr(self._idevice))

            # and update the renamed storage name:
            old_name = self._storageName
            for resource in preMergePackage.resources[self.checksum]:
                if resource._storageName == old_name:
                    resource._storageName = new_name
                    # And also update references to this resource
                    # in its content, according to the specific _idevice
                    updateIdevice(resource)
Beispiel #45
0
class Config:
    """
    The Config class contains the configuration information for eXe.
    """

    # Class attributes
    optionNames = {
        'system': (
            'webDir',
            'xulDir',
            'port',
            'dataDir',
            'configDir',
            'localeDir',
            'browserPath',
        ),
        'user': ('locale', 'latexpath'),
    }

    def __init__(self):
        """
        Initialise
        """
        self.configPath = None
        self.configParser = ConfigParser(self.onWrite)
        # Set default values
        # exePath is the whole path and filename of the exe executable
        self.exePath = Path(sys.argv[0]).abspath()
        # webDir is the parent directory for styles,scripts and templates
        self.webDir = self.exePath.dirname()
        # xulDir is the parent directory for styles,scripts and templates
        self.xulDir = self.exePath.dirname()
        # localeDir is the base directory where all the locales are stored
        self.localeDir = self.exePath.dirname() / "locale"
        # port is the port the exe webserver will listen on
        # (previous default, which earlier users might still use, was 8081)
        self.port = 51235
        # dataDir is the default directory that is shown to the user
        # to save packages and exports in
        self.dataDir = Path(".")
        # configDir is the dir for storing user profiles
        # and user made idevices and the config file
        self.configDir = Path(".")
        # browserPath is the entire pathname to firefox
        self.browserPath = Path("firefox")
        # locale is the language of the user
        self.locale = chooseDefaultLocale(self.localeDir)
        # internalAnchors indicate which exe_tmp_anchor tags to generate for each tinyMCE field
        # available values = "enable_all", "disable_autotop", or "disable_all"
        self.internalAnchors = "enable_all"
        # styles is the list of style names available for loading
        self.styles = []
        # The documents that we've recently looked at
        self.recentProjects = []
        # canonical (English) names of iDevices not to show in the iDevice pane
        self.hiddeniDevices = []
        # likewise, a canonical (English) names of iDevices not to show in the
        # iDevice pane but, contrary to the hiddens, these are ones that the
        # configuration can specify to turn ON:
        self.deprecatediDevices = [ "flash with text", "flash movie", "mp3", \
                                    "attachment"]
        # by default, only allow embedding of media types for which a
        # browser plugin is found:
        self.assumeMediaPlugins = False
        # Let our children override our defaults depending
        # on the OS that we're running on
        self._overrideDefaultVals()
        # Try to make the defaults a little intelligent
        # Under devel trees, webui is the default webdir
        self.webDir = Path(self.webDir)
        if not (self.webDir/'scripts').isdir() \
           and (self.webDir/'webui').isdir():
            self.webDir /= 'webui'
        # Under devel trees, xului is the default xuldir
        self.xulDir = Path(self.xulDir)
        if not (self.xulDir/'scripts').isdir() \
           and (self.xulDir/'xului').isdir():
            self.xulDir /= 'xului'
        # Latex distribution path if environment wasn't set properly
        self.latexpath = ""
        # Find where the config file will be saved
        self.__setConfigPath()
        # Fill in any undefined config options with our defaults
        self._writeDefaultConfigFile()
        # Now we are ready to serve the application
        self.loadSettings()
        self.setupLogging()
        self.loadStyles()
        self.loadLocales()

    def _overrideDefaultVals(self):
        """
        Override this to override the
        default config values
        """

    def _getConfigPathOptions(self):
        """
        Override this to give a list of
        possible config filenames
        in order of preference
        """
        return ['exe.conf']

    def _writeDefaultConfigFile(self):
        """
        [Over]writes 'self.configPath' with a default config file 
        (auto write is on so we don't need to write the file at the end)
        """
        for sectionName, optionNames in self.optionNames.items():
            for optionName in optionNames:
                defaultVal = getattr(self, optionName)
                self.configParser.setdefault(sectionName, optionName,
                                             defaultVal)
        # Logging can't really be changed from inside the program at the moment...
        self.configParser.setdefault('logging', 'root', 'INFO')

    def _getWinFolder(self, code):
        """
        Gets one of the windows famous directorys
        depending on 'code'
        Possible values can be found at:
        http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/enums/csidl.asp#CSIDL_WINDOWS
        """
        from ctypes import WinDLL, create_unicode_buffer
        dll = WinDLL('shell32')
        # The '5' and the '0' from the below call come from
        # google: "ShellSpecialConstants site:msdn.microsoft.com"
        result = create_unicode_buffer(260)
        resource = dll.SHGetFolderPathW(None, code, None, 0, result)
        if resource != 0:
            return Path('')
        else:
            return Path(result.value)

    def __setConfigPath(self):
        """
        sets self.configPath to the filename of the config file that we'll
        use.
        In descendant classes set self.configFileOptions to a list
        of directories where the configDir should be in order of preference.
        If no config files can be found in these dirs, it will
        force creation of the config file in the top dir
        """
        # If there's an EXECONF environment variable, use it
        self.configPath = None
        configFileOptions = map(Path, self._getConfigPathOptions())
        if "EXECONF" in os.environ:
            envconf = Path(os.environ["EXECONF"])
            if envconf.isfile():
                self.configPath = os.environ["EXECONF"]
        # Otherwise find the most appropriate existing file
        if self.configPath is None:
            for confPath in configFileOptions:
                if confPath.isfile():
                    self.configPath = confPath
                    break
            else:
                # If no config files exist, create and use the
                # first one on the list
                self.configPath = configFileOptions[0]
                folder = self.configPath.abspath().dirname()
                if not folder.exists():
                    folder.makedirs()
                self.configPath.touch()
        # Now make our configParser
        self.configParser.read(self.configPath)
        self.configParser.autoWrite = True

    def upgradeFile(self):
        """
        Called before loading the config file,
        removes or upgrades any old settings.
        """
        if self.configParser.has_section('system'):
            system = self.configParser.system
            if system.has_option('appDataDir'):
                # Older config files had configDir stored as appDataDir
                self.configDir = Path(system.appDataDir)
                # We'll just upgrade their config file for them for now...
                system.configDir = self.configDir
                del system.appDataDir
            if system.has_option('greDir'):
                # No longer used, system should automatically support
                del system.greDir

    def loadSettings(self):
        """
        Loads the settings from the exe.conf file.
        Overrides the defaults set in __init__
        """

        # Set up the parser so that if a certain value is not in the config
        # file, it will use the value from our default values
        def defVal(dummy, option):
            """If something is not in the config file, just use the default in
            'self'"""
            return getattr(self, option)

        self.configParser.defaultValue = defVal
        self.upgradeFile()
        # System Section
        if self.configParser.has_section('system'):
            system = self.configParser.system
            self.webDir = Path(system.webDir)
            self.xulDir = Path(system.xulDir)
            self.localeDir = Path(system.localeDir)
            self.port = int(system.port)
            self.browserPath = Path(system.browserPath)
            self.dataDir = Path(system.dataDir)
            self.configDir = Path(system.configDir)

            self.assumeMediaPlugins = False
            if self.configParser.has_option('system', \
                    'assumeMediaPlugins'):
                value = system.assumeMediaPlugins.strip().lower()
                if value == "1" or value == "yes" or value == "true" or \
                    value == "on":
                    self.assumeMediaPlugins = True

        # If the dataDir points to some other dir, fix it
        if not self.dataDir.isdir():
            self.dataDir = tempfile.gettempdir()
        # make the webDir absolute, to hide path joins of relative paths
        self.webDir = self.webDir.expand().abspath()
        # If the configDir doesn't exist (as it may be a default setting with a
        # new installation) create it
        if not self.configDir.exists():
            self.configDir.mkdir()

        # Get the list of recently opened projects
        self.recentProjects = []
        if self.configParser.has_section('recent_projects'):
            recentProjectsSection = self.configParser.recent_projects
            for key, path in recentProjectsSection.items():
                self.recentProjects.append(path)

        # Load the list of "hidden" iDevices
        self.hiddeniDevices = []
        if self.configParser.has_section('idevices'):
            idevicesSection = self.configParser.idevices
            for key, value in idevicesSection.items():
                # emulate standard library's getboolean()
                value = value.strip().lower()
                if value == "0" or value == "no" or value == "false" or \
                        value == "off":
                    self.hiddeniDevices.append(key.lower())

        #self.deprecatediDevices = [ "flash with text", "flash movie", ...]
        # and UN-Load from the list of "deprecated" iDevices
        if self.configParser.has_section('deprecated'):
            deprecatedSection = self.configParser.deprecated
            for key, value in deprecatedSection.items():
                # emulate standard library's getboolean()
                value = value.strip().lower()
                if value == "1" or value == "yes" or value == "true" or \
                        value == "on":
                    if key.lower() in self.deprecatediDevices:
                        self.deprecatediDevices.remove(key.lower())

        # Load the "user" section
        if self.configParser.has_section('user'):
            if self.configParser.user.has_option('internalAnchors'):
                self.internalAnchors = self.configParser.user.internalAnchors
            if self.configParser.user.has_option('locale'):
                self.locale = self.configParser.user.locale
                return
        self.locale = chooseDefaultLocale(self.localeDir)

    def onWrite(self, configParser):
        """
        Called just before the config file is written.
        We use it to fill out any settings that are stored here and 
        not in the config parser itself
        """
        # Recent projects
        self.configParser.delete('recent_projects')
        recentProjectsSection = self.configParser.addSection('recent_projects')
        for num, path in enumerate(self.recentProjects):
            recentProjectsSection[str(num)] = path

    def setupLogging(self):
        """
        setup logging file
        """
        try:
            hdlr = RotatingFileHandler(self.configDir / 'exe.log', 'a', 500000,
                                       10)
            hdlr.doRollover()
        except OSError:
            # ignore the error we get if the log file is logged
            hdlr = logging.FileHandler(self.configDir / 'exe.log')

        format = "%(asctime)s %(name)s %(levelname)s %(message)s"
        log = logging.getLogger()
        hdlr.setFormatter(logging.Formatter(format))
        log.addHandler(hdlr)

        loggingLevels = {
            "DEBUG": logging.DEBUG,
            "INFO": logging.INFO,
            "WARNING": logging.WARNING,
            "ERROR": logging.ERROR,
            "CRITICAL": logging.CRITICAL
        }

        if self.configParser.has_section('logging'):
            for logger, level in self.configParser._sections["logging"].items(
            ):
                if logger == "root":
                    logging.getLogger().setLevel(loggingLevels[level])
                else:
                    logging.getLogger(logger).setLevel(loggingLevels[level])

        log.info("************** eXe logging started **************")
        log.info("configPath  = %s" % self.configPath)
        log.info("exePath     = %s" % self.exePath)
        log.info("browserPath = %s" % self.browserPath)
        log.info("webDir      = %s" % self.webDir)
        log.info("xulDir      = %s" % self.xulDir)
        log.info("localeDir   = %s" % self.localeDir)
        log.info("port        = %d" % self.port)
        log.info("dataDir     = %s" % self.dataDir)
        log.info("configDir   = %s" % self.configDir)
        log.info("locale      = %s" % self.locale)
        log.info("internalAnchors = %s" % self.internalAnchors)

    def loadStyles(self):
        """
        Scans the eXe style directory and builds a list of styles
        """
        log = logging.getLogger()
        self.styles = []
        styleDir = self.webDir / "style"
        localeStyleDir = self.configDir / "style"
        if not os.path.exists(localeStyleDir):
            os.makedirs(localeStyleDir)

        log.debug("loadStyles from %s" % styleDir)

        for subDir in styleDir.dirs():
            if self.__checkStyle(subDir):
                styleName = subDir.basename()
                log.debug(" adding style to style/%s" % styleName)
                self.styles.append(styleName)
        # adding style from config to style/locale
        for subDir in localeStyleDir.dirs():
            if self.__checkStyle(subDir):
                styleName = "locale/" + subDir.basename()
                log.debug(" adding locale style to style/%s" % styleName)
                self.styles.append(styleName)

    def __checkStyle(self, style):
        '''Checks if it's valid style'''
        styleSheet = style / 'content.css'
        return styleSheet.exists()

    def loadLocales(self):
        """
        Scans the eXe locale directory and builds a list of locales
        """
        log = logging.getLogger()
        log.debug("loadLocales")
        gettext.install('exe', self.localeDir, True)
        self.locales = {}
        for subDir in self.localeDir.dirs():
            if (subDir / 'LC_MESSAGES' / 'exe.mo').exists():
                self.locales[subDir.basename()] = \
                    gettext.translation('exe',
                                        self.localeDir,
                                        languages=[str(subDir.basename())])
                if subDir.basename() == self.locale:
                    locale = subDir.basename()
                    log.debug(" loading locale %s" % locale)
                    self.locales[locale].install(unicode=True)
Beispiel #46
0
 def __init__(self):
     """
     Initialise
     """
     self.configPath = None
     self.configParser = ConfigParser(self.onWrite)
     # Set default values
     # exePath is the whole path and filename of the exe executable
     self.exePath = Path(sys.argv[0]).abspath()
     # webDir is the parent directory for styles,scripts and templates
     self.webDir = self.exePath.dirname()
     # xulDir is the parent directory for styles,scripts and templates
     self.xulDir = self.exePath.dirname()
     # localeDir is the base directory where all the locales are stored
     self.localeDir = self.exePath.dirname() / "locale"
     # port is the port the exe webserver will listen on
     # (previous default, which earlier users might still use, was 8081)
     self.port = 51235
     # dataDir is the default directory that is shown to the user
     # to save packages and exports in
     self.dataDir = Path(".")
     # configDir is the dir for storing user profiles
     # and user made idevices and the config file
     self.configDir = Path(".")
     # browserPath is the entire pathname to firefox
     self.browserPath = Path("firefox")
     # locale is the language of the user
     self.locale = chooseDefaultLocale(self.localeDir)
     # internalAnchors indicate which exe_tmp_anchor tags to generate for each tinyMCE field
     # available values = "enable_all", "disable_autotop", or "disable_all"
     self.internalAnchors = "enable_all"
     # styles is the list of style names available for loading
     self.styles = []
     # The documents that we've recently looked at
     self.recentProjects = []
     # canonical (English) names of iDevices not to show in the iDevice pane
     self.hiddeniDevices = []
     # likewise, a canonical (English) names of iDevices not to show in the
     # iDevice pane but, contrary to the hiddens, these are ones that the
     # configuration can specify to turn ON:
     self.deprecatediDevices = [ "flash with text", "flash movie", "mp3", \
                                 "attachment"]
     # by default, only allow embedding of media types for which a
     # browser plugin is found:
     self.assumeMediaPlugins = False
     # Let our children override our defaults depending
     # on the OS that we're running on
     self._overrideDefaultVals()
     # Try to make the defaults a little intelligent
     # Under devel trees, webui is the default webdir
     self.webDir = Path(self.webDir)
     if not (self.webDir/'scripts').isdir() \
        and (self.webDir/'webui').isdir():
         self.webDir /= 'webui'
     # Under devel trees, xului is the default xuldir
     self.xulDir = Path(self.xulDir)
     if not (self.xulDir/'scripts').isdir() \
        and (self.xulDir/'xului').isdir():
         self.xulDir /= 'xului'
     # Latex distribution path if environment wasn't set properly
     self.latexpath = ""
     # Find where the config file will be saved
     self.__setConfigPath()
     # Fill in any undefined config options with our defaults
     self._writeDefaultConfigFile()
     # Now we are ready to serve the application
     self.loadSettings()
     self.setupLogging()
     self.loadStyles()
     self.loadLocales()
Beispiel #47
0
 def handleAudioVideoTags(self, htmlContent, mediaParams = {}):
     htmlContentLower = htmlContent.lower()
     
     tagNames = ['audio', 'video']
     
     countAudio = 0
     countVideo = 0
     audioInFile = ""
     videoInFile = ""
     videoOutFile = ""
     
     startIndex = 0
     while startIndex != -1:
         startIndex = self._findNextTagStart(htmlContentLower, startIndex, tagNames)
         if startIndex == -1:
             break
         
         tagName = htmlContentLower[startIndex+1:startIndex+6]
         
         mediaName = self._getSrcForTag(htmlContent, startIndex)
         
         #find the media base name without the extension and the current extension
         mediaNameParts = os.path.splitext(mediaName)
         if len(mediaNameParts) < 2:
             #does not have a file extension - confused!
             #TODO: More warning stuff here
             break
         
         mediaBaseName = mediaNameParts[0]
         mediaExtension = mediaNameParts[1][1:] 
         workingDir = ExportMediaConverter.workingDir
         conversionCommandBase = ""
         inFilePath = workingDir/mediaName
             
         
         #handle audio conversion
         if tagName == "audio":
             countAudio = countAudio + 1
             
             targetFormat = self.configParser.get("media", "audioformat")
             
             if targetFormat == "au":
                 conversionCommandBase = ExportMediaConverter.appConfig.audioMediaConverter_au
             elif targetFormat == "mp3":
                 conversionCommandBase = ExportMediaConverter.appConfig.audioMediaConverter_mp3
             elif targetFormat == "ogg":
                 conversionCommandBase = ExportMediaConverter.appConfig.audioMediaConverter_ogg
             elif targetFormat == "wav":
                 conversionCommandBase = ExportMediaConverter.appConfig.audioMediaConverter_wav
             
         if tagName == "video":
             countVideo = countVideo + 1
             
             targetFormat = self.configParser.get("media", "videoformat")
             
             if targetFormat == "3gp":
                 conversionCommandBase = ExportMediaConverter.appConfig.videoMediaConverter_3gp
             elif targetFormat == "mpg":
                 conversionCommandBase = ExportMediaConverter.appConfig.videoMediaConverter_mpg
             elif targetFormat == "ogv":
                 conversionCommandBase = ExportMediaConverter.appConfig.videoMediaConverter_ogv
             elif targetFormat == "avi":
                 conversionCommandBase = ExportMediaConverter.appConfig.videoMediaConverter_avi
             
         newFileName = mediaBaseName + "." + targetFormat
         outFilePath = workingDir + "/" + newFileName
         if tagName == "audio":
             audioInFile = mediaName
         elif tagName == "video":
             videoInFile = mediaName
             videoOutFile = newFileName
         
         workingDir = Path(inFilePath).parent
         
         cmdEnv = {'PATH' : os.environ['PATH'] }
         
         exeDir = globals.application.config.exePath.parent
         mediaToolsDir = str(exeDir/"mediaconverters")
         if sys.platform[:3] == "win":
             cmdEnv['PATH'] = mediaToolsDir + os.pathsep + cmdEnv['PATH']
             cmdEnv['SYSTEMROOT'] = os.environ['SYSTEMROOT']
             
         conversionCommand = conversionCommandBase  \
                 % {"infile" : mediaName, "outfile" : newFileName}
         print "Converting: run %s\n" % conversionCommand
         call(conversionCommand, shell=True, cwd=workingDir, env=cmdEnv)
         htmlContent = htmlContent.replace(mediaName, newFileName)
                 
         # go forward so we don't find the same one again
         startIndex = startIndex + 1
     
     #see if we have one audio and one video - in which case auto mix them
     if countVideo == 1 and countAudio == 1:
         audioInFileAbs = workingDir + "/" + audioInFile
         videoInFileAbs = workingDir + "/" + videoInFile
         combinedOutFile = workingDir + "/" + videoOutFile
         
         print "Mixing Video/Audio"
         mixCommand = ExportMediaConverter.appConfig.ffmpegPath + " -i %(audioin)s -i %(videoin)s -s qcif -vcodec h263 -acodec libvo_aacenc -ac 1 -ar 8000 -r 25 -ab 32 -y -aspect 4:3 %(videoout)s" \
             % { "audioin" : audioInFileAbs, "videoin" : videoInFileAbs, "videoout" : combinedOutFile}
             
         print "Running command %s \n" % mixCommand   
         
         call(mixCommand, shell=True)
     
     #remove the <script part that exe made for FF3- compatibility
     #TODO: potential case sensitivity issue here -but exe always makes lower case...
     startScriptIndex = self._findNextTagStart(htmlContent, 0, ["script"])
     if startScriptIndex != -1:
         endScriptIndex = htmlContent.find("</script>") + 9
         htmlContent = htmlContent[:startScriptIndex] + htmlContent[endScriptIndex:]
     
     return htmlContent    
Beispiel #48
0
    def loadSettings(self):
        """
        Loads the settings from the exe.conf file.
        Overrides the defaults set in __init__
        """

        # Set up the parser so that if a certain value is not in the config
        # file, it will use the value from our default values
        def defVal(dummy, option):
            """If something is not in the config file, just use the default in
            'self'"""
            return getattr(self, option)

        self.configParser.defaultValue = defVal
        self.upgradeFile()
        # System Section
        if self.configParser.has_section('system'):
            system = self.configParser.system
            self.webDir = Path(system.webDir)
            self.xulDir = Path(system.xulDir)
            self.localeDir = Path(system.localeDir)
            self.port = int(system.port)
            self.browserPath = Path(system.browserPath)
            self.dataDir = Path(system.dataDir)
            self.configDir = Path(system.configDir)

            self.assumeMediaPlugins = False
            if self.configParser.has_option('system', \
                    'assumeMediaPlugins'):
                value = system.assumeMediaPlugins.strip().lower()
                if value == "1" or value == "yes" or value == "true" or \
                    value == "on":
                    self.assumeMediaPlugins = True

        # If the dataDir points to some other dir, fix it
        if not self.dataDir.isdir():
            self.dataDir = tempfile.gettempdir()
        # make the webDir absolute, to hide path joins of relative paths
        self.webDir = self.webDir.expand().abspath()
        # If the configDir doesn't exist (as it may be a default setting with a
        # new installation) create it
        if not self.configDir.exists():
            self.configDir.mkdir()

        # Get the list of recently opened projects
        self.recentProjects = []
        if self.configParser.has_section('recent_projects'):
            recentProjectsSection = self.configParser.recent_projects
            for key, path in recentProjectsSection.items():
                self.recentProjects.append(path)

        # Load the list of "hidden" iDevices
        self.hiddeniDevices = []
        if self.configParser.has_section('idevices'):
            idevicesSection = self.configParser.idevices
            for key, value in idevicesSection.items():
                # emulate standard library's getboolean()
                value = value.strip().lower()
                if value == "0" or value == "no" or value == "false" or \
                        value == "off":
                    self.hiddeniDevices.append(key.lower())

        #self.deprecatediDevices = [ "flash with text", "flash movie", ...]
        # and UN-Load from the list of "deprecated" iDevices
        if self.configParser.has_section('deprecated'):
            deprecatedSection = self.configParser.deprecated
            for key, value in deprecatedSection.items():
                # emulate standard library's getboolean()
                value = value.strip().lower()
                if value == "1" or value == "yes" or value == "true" or \
                        value == "on":
                    if key.lower() in self.deprecatediDevices:
                        self.deprecatediDevices.remove(key.lower())

        # Load the "user" section
        if self.configParser.has_section('user'):
            if self.configParser.user.has_option('internalAnchors'):
                self.internalAnchors = self.configParser.user.internalAnchors
            if self.configParser.user.has_option('locale'):
                self.locale = self.configParser.user.locale
                return
        self.locale = chooseDefaultLocale(self.localeDir)
Beispiel #49
0
class Epub3Export(object):
    """
    Exports an eXe package as a epub 3 package
    The 'Hello World' of a epub 3 publication might contain files:
        mimetype
        META-INF/container.xml
        Content/HelloWorld.opf
        Content/HelloWorld.xhtml
    """
    def __init__(self, config, styleDir, filename):
        """
        Initialize
        'styleDir' is the directory from which we will copy our style sheets
        (and some gifs)
        """
        self.config = config
        self.imagesDir = config.webDir / "images"
        self.scriptsDir = config.webDir / "scripts"
        self.cssDir = config.webDir / "css"
        self.templatesDir = config.webDir / "templates"
        self.schemasDir = config.webDir / "schemas/ims"
        self.styleDir = Path(styleDir)
        self.filename = Path(filename)
        self.pages = []

    def export(self, package):
        """
        Export epub 3 package
        """
        # First do the export to a temporary directory
        outputDir = TempDirPath()

        '''
        fileDir = outputDir/"META-INF"
        fileDir.mkdir()
        fileDir = outputDir/"Content"
        fileDir.mkdir()
        '''

        metainfPages = Path(outputDir.abspath() + '/META-INF')
        # metainfPages = outputDir/'META-INF'
        metainfPages.mkdir()
        contentPages = Path(outputDir.abspath() + '/EPUB')
        # contentPages = outputDir/'Content'
        contentPages.mkdir()
        # print contentPages.abspath()
        # print outputDir.abspath()

        # Export the package content
        self.pages = [Epub3Cover("cover", 1, package.root)]

        self.generatePages(package.root, 2)
        uniquifyNames(self.pages)

        cover = None
        for page in self.pages:
            page.save(contentPages)
            if hasattr(page, 'cover'):
                cover = page.cover

        # Create mimetype file
        mimetypeFile = open(outputDir.abspath() + '/mimetype', "w")
        mimetypeFile.write('application/epub+zip')
        mimetypeFile.close()

        # Copy the style sheet files to the output dir
        # But not nav.css
        styleFiles = [self.styleDir / '..' / 'base.css']
        styleFiles += [self.styleDir / '..' / 'popup_bg.gif']
        styleFiles += [f for f in self.styleDir.files("*.css") if f.basename() != "nav.css"]
        styleFiles += self.styleDir.files("*.jpg")
        styleFiles += self.styleDir.files("*.gif")
        styleFiles += self.styleDir.files("*.png")
        styleFiles += self.styleDir.files("*.js")
        styleFiles += self.styleDir.files("*.html")
        styleFiles += self.styleDir.files("*.ttf")
        styleFiles += self.styleDir.files("*.eot")
        styleFiles += self.styleDir.files("*.otf")
        styleFiles += self.styleDir.files("*.woff")
        # FIXME for now, only copy files referenced in Common Cartridge
        # this really should apply to all exports, but without a manifest
        # of the files needed by an included stylesheet it is too restrictive

        package.resourceDir.copyfiles(contentPages)

        self.styleDir.copylist(styleFiles, contentPages)
        self.scriptsDir.copylist(('common.js',), contentPages)

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        hasGallery = False
        hasFX = False
        hasSH = False
        hasGames = False
        hasWikipedia = False
        isBreak = False
        hasInstructions = False
        hasTooltips = False

        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'mojomagnify.js' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True
                if not hasGallery:
                    hasGallery = common.ideviceHasGallery(idevice)
                if not hasFX:
                    hasFX = common.ideviceHasFX(idevice)
                if not hasSH:
                    hasSH = common.ideviceHasSH(idevice)
                if not hasGames:
                    hasGames = common.ideviceHasGames(idevice)
                if not hasWikipedia:
                    if 'WikipediaIdevice' == idevice.klass:
                        hasWikipedia = True
                if not hasInstructions:
                    if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                        hasInstructions = True
                if not hasTooltips:
                    hasTooltips = common.ideviceHasTooltips(idevice)

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(contentPages / 'flowPlayer.swf')
            controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
            controlsfile.copyfile(contentPages / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'mojomagnify.js')
            videofile.copyfile(contentPages / 'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(contentPages / 'xspf_player.swf')
        if hasGallery:
            exeLightbox = (self.scriptsDir / 'exe_lightbox')
            exeLightbox.copyfiles(contentPages)
        if hasFX:
            exeEffects = (self.scriptsDir / 'exe_effects')
            exeEffects.copyfiles(contentPages)
        if hasSH:
            exeSH = (self.scriptsDir / 'exe_highlighter')
            exeSH.copyfiles(contentPages)
        if hasGames:
            exeGames = (self.scriptsDir / 'exe_games')
            exeGames.copyfiles(contentPages)
        if hasWikipedia:
            wikipediaCSS = (self.cssDir / 'exe_wikipedia.css')
            wikipediaCSS.copyfile(contentPages / 'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self, contentPages)
            common.copyFileIfNotInStyle('stock-stop.png', self, contentPages)
        if hasTooltips:
            exe_tooltips = (self.scriptsDir / 'exe_tooltips')
            exe_tooltips.copyfiles(contentPages)

        my_style = G.application.config.styleStore.getStyle(package.style)
        if my_style.hasValidConfig:
            if my_style.get_jquery() == True:
                jsFile = (self.scriptsDir / 'exe_jquery.js')
                jsFile.copyfile(contentPages / 'exe_jquery.js')
        else:
            jsFile = (self.scriptsDir / 'exe_jquery.js')
            jsFile.copyfile(contentPages / 'exe_jquery.js')

#         if hasattr(package, 'exportSource') and package.exportSource:
#             (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd')
#             (outputDir / 'content.data').write_bytes(encodeObject(package))
#             (outputDir / 'contentv3.xml').write_bytes(encodeObjectToXML(package))

        if package.license == "license GFDL":
            # include a copy of the GNU Free Documentation Licence
            (self.templatesDir / 'fdl.html').copyfile(contentPages / 'fdl.html')

        # Create the nav.xhtml file
        container = NavEpub3(self.pages, contentPages)
        container.save()

        # Create the publication file
        publication = PublicationEpub3(self.config, contentPages, package, self.pages, cover)
        publication.save("package.opf")

        # Create the container file
        container = ContainerEpub3(metainfPages)
        container.save("container.xml")

        # Zip it up!
        self.filename.safeSave(self.doZip, _(u'EXPORT FAILED!\nLast succesful export is %s.'), outputDir)
        # Clean up the temporary dir

        outputDir.rmtree()

    def doZip(self, fileObj, outputDir):
        """
        Actually does the zipping of the file. Called by 'Path.safeSave'
        """
        zipped = ZipFile(fileObj, "w")

        mimetype = outputDir / "mimetype"
        zipped.write(mimetype, "mimetype", ZIP_STORED)

        for epubFile in outputDir.walkfiles():
            if epubFile.basename() == 'mimetype':
                continue
            relativePath = epubFile.basename()
            parentdir = epubFile.splitpath()[0]
            while (outputDir.basename() != parentdir.basename()):
                relativePath = parentdir.basename() / relativePath
                parentdir = parentdir.splitpath()[0]

            zipped.write(epubFile,
                             relativePath.encode('utf8'),
                             compress_type=ZIP_DEFLATED)
        zipped.close()

    def generatePages(self, node, depth):
        """
        Recursive function for exporting a node.
        'node' is the node that we are making a page for
        'depth' is the number of ancestors that the page has +1 (ie. root is 1)
        """
        pageName = node.titleShort.lower().replace(" ", u"_")
        pageName = re.sub(r"\W", "", pageName)
        if not pageName:
            pageName = u"__"

        if pageName[0] in [unicode(i) for i in range(0, 10)]:
            pageName = u'_' + pageName

        page = Epub3Page(pageName, depth, node)

        self.pages.append(page)
        for child in node.children:
            self.generatePages(child, depth + 1)
Beispiel #50
0
    def export(self, package):
        """
        Export epub 3 package
        """
        # First do the export to a temporary directory
        outputDir = TempDirPath()

        '''
        fileDir = outputDir/"META-INF"
        fileDir.mkdir()
        fileDir = outputDir/"Content"
        fileDir.mkdir()
        '''

        metainfPages = Path(outputDir.abspath() + '/META-INF')
        # metainfPages = outputDir/'META-INF'
        metainfPages.mkdir()
        contentPages = Path(outputDir.abspath() + '/EPUB')
        # contentPages = outputDir/'Content'
        contentPages.mkdir()
        # print contentPages.abspath()
        # print outputDir.abspath()

        # Export the package content
        self.pages = [Epub3Cover("cover", 1, package.root)]

        self.generatePages(package.root, 2)
        uniquifyNames(self.pages)

        cover = None
        for page in self.pages:
            page.save(contentPages)
            if hasattr(page, 'cover'):
                cover = page.cover

        # Create mimetype file
        mimetypeFile = open(outputDir.abspath() + '/mimetype', "w")
        mimetypeFile.write('application/epub+zip')
        mimetypeFile.close()

        # Copy the style sheet files to the output dir
        # But not nav.css
        styleFiles = [self.styleDir / '..' / 'base.css']
        styleFiles += [self.styleDir / '..' / 'popup_bg.gif']
        styleFiles += [f for f in self.styleDir.files("*.css") if f.basename() != "nav.css"]
        styleFiles += self.styleDir.files("*.jpg")
        styleFiles += self.styleDir.files("*.gif")
        styleFiles += self.styleDir.files("*.png")
        styleFiles += self.styleDir.files("*.js")
        styleFiles += self.styleDir.files("*.html")
        styleFiles += self.styleDir.files("*.ttf")
        styleFiles += self.styleDir.files("*.eot")
        styleFiles += self.styleDir.files("*.otf")
        styleFiles += self.styleDir.files("*.woff")
        # FIXME for now, only copy files referenced in Common Cartridge
        # this really should apply to all exports, but without a manifest
        # of the files needed by an included stylesheet it is too restrictive

        package.resourceDir.copyfiles(contentPages)

        self.styleDir.copylist(styleFiles, contentPages)
        self.scriptsDir.copylist(('common.js',), contentPages)

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        hasGallery = False
        hasFX = False
        hasSH = False
        hasGames = False
        hasWikipedia = False
        isBreak = False
        hasInstructions = False
        hasTooltips = False

        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'mojomagnify.js' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True
                if not hasGallery:
                    hasGallery = common.ideviceHasGallery(idevice)
                if not hasFX:
                    hasFX = common.ideviceHasFX(idevice)
                if not hasSH:
                    hasSH = common.ideviceHasSH(idevice)
                if not hasGames:
                    hasGames = common.ideviceHasGames(idevice)
                if not hasWikipedia:
                    if 'WikipediaIdevice' == idevice.klass:
                        hasWikipedia = True
                if not hasInstructions:
                    if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                        hasInstructions = True
                if not hasTooltips:
                    hasTooltips = common.ideviceHasTooltips(idevice)

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(contentPages / 'flowPlayer.swf')
            controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
            controlsfile.copyfile(contentPages / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'mojomagnify.js')
            videofile.copyfile(contentPages / 'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(contentPages / 'xspf_player.swf')
        if hasGallery:
            exeLightbox = (self.scriptsDir / 'exe_lightbox')
            exeLightbox.copyfiles(contentPages)
        if hasFX:
            exeEffects = (self.scriptsDir / 'exe_effects')
            exeEffects.copyfiles(contentPages)
        if hasSH:
            exeSH = (self.scriptsDir / 'exe_highlighter')
            exeSH.copyfiles(contentPages)
        if hasGames:
            exeGames = (self.scriptsDir / 'exe_games')
            exeGames.copyfiles(contentPages)
        if hasWikipedia:
            wikipediaCSS = (self.cssDir / 'exe_wikipedia.css')
            wikipediaCSS.copyfile(contentPages / 'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self, contentPages)
            common.copyFileIfNotInStyle('stock-stop.png', self, contentPages)
        if hasTooltips:
            exe_tooltips = (self.scriptsDir / 'exe_tooltips')
            exe_tooltips.copyfiles(contentPages)

        my_style = G.application.config.styleStore.getStyle(package.style)
        if my_style.hasValidConfig:
            if my_style.get_jquery() == True:
                jsFile = (self.scriptsDir / 'exe_jquery.js')
                jsFile.copyfile(contentPages / 'exe_jquery.js')
        else:
            jsFile = (self.scriptsDir / 'exe_jquery.js')
            jsFile.copyfile(contentPages / 'exe_jquery.js')

#         if hasattr(package, 'exportSource') and package.exportSource:
#             (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd')
#             (outputDir / 'content.data').write_bytes(encodeObject(package))
#             (outputDir / 'contentv3.xml').write_bytes(encodeObjectToXML(package))

        if package.license == "license GFDL":
            # include a copy of the GNU Free Documentation Licence
            (self.templatesDir / 'fdl.html').copyfile(contentPages / 'fdl.html')

        # Create the nav.xhtml file
        container = NavEpub3(self.pages, contentPages)
        container.save()

        # Create the publication file
        publication = PublicationEpub3(self.config, contentPages, package, self.pages, cover)
        publication.save("package.opf")

        # Create the container file
        container = ContainerEpub3(metainfPages)
        container.save("container.xml")

        # Zip it up!
        self.filename.safeSave(self.doZip, _(u'EXPORT FAILED!\nLast succesful export is %s.'), outputDir)
        # Clean up the temporary dir

        outputDir.rmtree()
Beispiel #51
0
    def export(self, package):
        """
        Export epub 3 package
        """
        # First do the export to a temporary directory
        outputDir = TempDirPath()

        '''
        fileDir = outputDir/"META-INF"
        fileDir.mkdir()
        fileDir = outputDir/"Content"
        fileDir.mkdir()
        '''

        metainfPages = Path(outputDir.abspath() + '/META-INF')
        # metainfPages = outputDir/'META-INF'
        metainfPages.mkdir()
        contentPages = Path(outputDir.abspath() + '/EPUB')
        # contentPages = outputDir/'Content'
        contentPages.mkdir()
        # print contentPages.abspath()
        # print outputDir.abspath()

        # Export the package content
        self.pages = [Epub3Cover("cover", 1, package.root)]

        self.generatePages(package.root, 2)
        uniquifyNames(self.pages)

        cover = None
        for page in self.pages:
            page.save(contentPages, self.pages)
            if hasattr(page, 'cover'):
                cover = page.cover

        # Create mimetype file
        mimetypeFile = open(outputDir.abspath() + '/mimetype', "w")
        mimetypeFile.write('application/epub+zip')
        mimetypeFile.close()

        # Create common_i18n file
        langFile = open(contentPages + '/common_i18n.js', "w")
        langFile.write(common.getJavaScriptStrings(False))
        langFile.close()

        # Copy the style files to the output dir
        # But not nav.css
        styleFiles = [self.styleDir /'..'/ 'popup_bg.gif']
        styleFiles += [f for f in self.styleDir.files("*.*") if f.basename() not in ['nav.css']]

        # FIXME for now, only copy files referenced in Common Cartridge
        # this really should apply to all exports, but without a manifest
        # of the files needed by an included stylesheet it is too restrictive

        # Add fallback document for possible image links
        if Path(self.styleDir/'fallback.xhtml').exists():
            styleFiles += [self.styleDir /'fallback.xhtml']
        else:
            styleFiles += [self.styleDir/'..'/'fallback.xhtml']

        # copy the package's resource files
        for resourceFile in package.resourceDir.walkfiles():
            fn = package.resourceDir.relpathto(resourceFile)

            if ("/" in fn):
                Dir = Path(contentPages/fn[:fn.rindex("/")])
                if not Dir.exists():
                    Dir.makedirs()

                resourceFile.copy(contentPages/Dir)
            else:
                resourceFile.copy(contentPages)

        self.styleDir.copylist(styleFiles, contentPages)

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        hasGallery = False
        hasFX = False
        hasSH = False
        hasGames = False
        hasElpLink = False
        hasWikipedia = False
        isBreak = False
        hasInstructions = False
        hasTooltips = False
        hasABCMusic = False

        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasTooltips and hasABCMusic):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'mojomagnify.js' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True
                if not hasGallery:
                    hasGallery = common.ideviceHasGallery(idevice)
                if not hasFX:
                    hasFX = common.ideviceHasFX(idevice)
                if not hasSH:
                    hasSH = common.ideviceHasSH(idevice)
                if not hasGames:
                    hasGames = common.ideviceHasGames(idevice)
                if not hasElpLink:
                    hasElpLink = common.ideviceHasElpLink(idevice,package)
                if not hasWikipedia:
                    if 'WikipediaIdevice' == idevice.klass:
                        hasWikipedia = True
                if not hasInstructions:
                    if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                        hasInstructions = True
                if not hasTooltips:
                    hasTooltips = common.ideviceHasTooltips(idevice)
                if not hasABCMusic:
                    hasABCMusic = common.ideviceHasABCMusic(idevice)

            common.exportJavaScriptIdevicesFiles(page.node.idevices, contentPages);

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(contentPages / 'flowPlayer.swf')
            controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
            controlsfile.copyfile(contentPages / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'mojomagnify.js')
            videofile.copyfile(contentPages / 'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(contentPages / 'xspf_player.swf')
        if hasGallery:
            exeLightbox = (self.scriptsDir / 'exe_lightbox')
            exeLightbox.copyfiles(contentPages)
        if hasFX:
            exeEffects = (self.scriptsDir / 'exe_effects')
            exeEffects.copyfiles(contentPages)
        if hasSH:
            exeSH = (self.scriptsDir / 'exe_highlighter')
            exeSH.copyfiles(contentPages)
        if hasGames:
            exeGames = (self.scriptsDir / 'exe_games')
            exeGames.copyfiles(contentPages)
            # Add game js string to common_i18n
            langGameFile = open(contentPages + '/common_i18n.js', "a")
            langGameFile.write(common.getGamesJavaScriptStrings(False))
            langGameFile.close()
        if hasElpLink or package.get_exportElp():
            # Export the elp file
            currentPackagePath = Path(package.filename)
            currentPackagePath.copyfile(contentPages/package.name+'.elp')
        if hasWikipedia:
            wikipediaCSS = (self.cssDir / 'exe_wikipedia.css')
            wikipediaCSS.copyfile(contentPages / 'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self, contentPages)
            common.copyFileIfNotInStyle('stock-stop.png', self, contentPages)
        if hasTooltips:
            exe_tooltips = (self.scriptsDir / 'exe_tooltips')
            exe_tooltips.copyfiles(contentPages)
        if hasABCMusic:
            pluginScripts = (self.scriptsDir/'tinymce_4/js/tinymce/plugins/abcmusic/export')
            pluginScripts.copyfiles(contentPages)

        my_style = G.application.config.styleStore.getStyle(package.style)
        if my_style.hasValidConfig:
            if my_style.get_jquery() == True:
                jsFile = (self.scriptsDir / 'exe_jquery.js')
                jsFile.copyfile(contentPages / 'exe_jquery.js')
        else:
            jsFile = (self.scriptsDir / 'exe_jquery.js')
            jsFile.copyfile(contentPages / 'exe_jquery.js')


        # Copy and minify CSS files
        css_files = getFilesCSSToMinify('epub3', self.styleDir)
        exportMinFileCSS(css_files, contentPages)

        # Copy and minify JS files
        js_files = getFilesJSToMinify('epub3', self.scriptsDir)
        exportMinFileJS(js_files, contentPages)

#         if hasattr(package, 'exportSource') and package.exportSource:
#             (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd')
#             (outputDir / 'content.data').write_bytes(encodeObject(package))
#             (outputDir / 'contentv3.xml').write_bytes(encodeObjectToXML(package))

        if package.license == "license GFDL":
            # include a copy of the GNU Free Documentation Licence
            (self.templatesDir / 'fdl.html').copyfile(contentPages / 'fdl.html')

        # Create the nav.xhtml file
        container = NavEpub3(self.pages, contentPages)
        container.save()

        # Create the publication file
        publication = PublicationEpub3(self.config, contentPages, package, self.pages, cover)
        publication.save("package.opf")

        # Create the container file
        container = ContainerEpub3(metainfPages)
        container.save("container.xml")

        # Zip it up!
        self.filename.safeSave(self.doZip, _(u'EXPORT FAILED!\nLast succesful export is %s.'), outputDir)
        # Clean up the temporary dir

        outputDir.rmtree()
Beispiel #52
0
class SinglePageExport(object):
    """
    SinglePageExport will export a package as a website of HTML pages
    """
    def __init__(self, stylesDir, outputDir, imagesDir, scriptsDir, cssDir, templatesDir):
        """
        'stylesDir' is the directory where we can copy the stylesheets from
        'outputDir' is the directory that will be [over]written
        with the website
        """
        self.html         = ""
        self.style        = None
        self.name         = None
        self.stylesDir    = Path(stylesDir)
        self.outputDir    = Path(outputDir)
        self.imagesDir    = Path(imagesDir)
        self.scriptsDir   = Path(scriptsDir)
        self.cssDir       = Path(cssDir)
        self.templatesDir = Path(templatesDir)
	self.page         = None

        # Create the output dir if it doesn't already exist
        if not self.outputDir.exists(): 
            self.outputDir.mkdir()


    def export(self, package, for_print=0):
        """ 
        Export web site
        Cleans up the previous packages pages and performs the export
        """
        self.style = package.style       
	
	self.page = SinglePage("index", 1, package.root)

        self.page.save(self.outputDir/"index.html", for_print)
	
	self.copyFiles(package)


    def copyFiles(self, package):
        """
        Copy all the files used by the website.
        """
        # Copy the style sheet files to the output dir
        # But not nav.css
        styleFiles  = [self.stylesDir/'..'/'base.css']
	styleFiles += [self.stylesDir/'..'/'popup_bg.gif']
        styleFiles += self.stylesDir.files("*.css")
        if "nav.css" in styleFiles:
            styleFiles.remove("nav.css")
        styleFiles += self.stylesDir.files("*.jpg")
        styleFiles += self.stylesDir.files("*.gif")
        styleFiles += self.stylesDir.files("*.png")
        styleFiles += self.stylesDir.files("*.js")
        styleFiles += self.stylesDir.files("*.html")
        styleFiles += self.stylesDir.files("*.ico")
        styleFiles += self.stylesDir.files("*.ttf")
        styleFiles += self.stylesDir.files("*.eot")
        styleFiles += self.stylesDir.files("*.otf")
        styleFiles += self.stylesDir.files("*.woff")
        self.stylesDir.copylist(styleFiles, self.outputDir)

        # copy the package's resource files
        package.resourceDir.copyfiles(self.outputDir)

        # copy script files. - with modification by lernmodule.net
        self.scriptsDir.copylist(('libot_drag.js', 'common.js', 'lernmodule_net.js'),
                                 self.outputDir)

        #JR Metemos los reproductores necesarios
        self.compruebaReproductores(self.page.node)


        if package.license == "GNU Free Documentation License":
            # include a copy of the GNU Free Documentation Licence
            (self.templatesDir/'fdl.html').copyfile(self.outputDir/'fdl.html')

    def compruebaReproductores(self, node):
        """
        Comprobamos si hay que meter algun reproductor
        """
        
    	# copy players for media idevices.                
        hasFlowplayer     = False
        hasMagnifier      = False
        hasXspfplayer     = False
        hasGallery        = False

    	for idevice in node.idevices:
    	    if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery):
    	    	break
    	    if not hasFlowplayer:
    	    	if 'flowPlayer.swf' in idevice.systemResources:
    	    		hasFlowplayer = True
    	    if not hasMagnifier:
    	    	if 'magnifier.swf' in idevice.systemResources:
    	    		hasMagnifier = True
    	    if not hasXspfplayer:
    		    if 'xspf_player.swf' in idevice.systemResources:
    			    hasXspfplayer = True
            if not hasGallery:
    			if 'GalleryIdevice' == idevice.klass:
    				hasGallery = True
                            
        if hasFlowplayer:
            videofile = (self.templatesDir/'flowPlayer.swf')
            videofile.copyfile(self.outputDir/'flowPlayer.swf')
            controlsfile = (self.templatesDir/'flowplayer.controls.swf')
            controlsfile.copyfile(self.outputDir/'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir/'magnifier.swf')
            videofile.copyfile(self.outputDir/'magnifier.swf')
        if hasXspfplayer:
            videofile = (self.templatesDir/'xspf_player.swf')
            videofile.copyfile(self.outputDir/'xspf_player.swf')
        if hasGallery:
            imageGalleryCSS = (self.cssDir/'exe_lightbox.css')
            imageGalleryCSS.copyfile(self.outputDir/'exe_lightbox.css') 
            imageGalleryJS = (self.scriptsDir/'exe_lightbox.js')
            imageGalleryJS.copyfile(self.outputDir/'exe_lightbox.js') 
            self.imagesDir.copylist(('exeGallery_actions.png', 'exeGallery_loading.gif'), self.outputDir)
            
        for child in node.children:
            self.compruebaReproductores(child)
Beispiel #53
0
    def _addOurselvesToPackage(self, oldPath):
        """
        Adds ourselves into self._package.resources.
        Don't call if self._package is None.
        Does no copying or anything. Just sticks us in the list and sets our storage name
        """
        # new safety mechanism for old corrupt packages which
        # have non-existent resources that are being deleted and such:
        if not hasattr(self, 'checksum') or self.checksum is None:
            if self._package is None:
                log.warn("Resource " + repr(self) + " has no checksum " \
                        + "(probably no source file), but is being removed "\
                        + "anyway, so ignoring.")
                return
            else:
                if oldPath.isfile():
                    log.warn("Resource " + repr(self) + " has no checksum; " \
                            + " adding and continuing...")
                    # see if a few basic checks here can get it going to add:
                    self.checksum = oldPath.md5
                else:
                    log.warn("Resource " + repr(self) + " has no checksum " \
                        + "(and no source file), and was being added to "\
                        + "package " + repr(self._package) + "; ignoring.")
                    return

        # Add ourselves to our new package's list of resources

        if not hasattr(self._package, 'resources'):
            log.error(
                "_AddOurselvesToPackage called with an invalid package: " +
                " no resources on package " + repr(self._package) +
                "; possibly after a deepcopy")
            return
        if not hasattr(self._package, 'resourceDir'):
            log.error(
                "_AddOurselvesToPackage called with an invalid package: " +
                " no resourceDir on package " + repr(self._package) +
                "; possibly an old/corrupt resource or package")
            return

        # We want to prevent eXe from removing images while loading a package as
        # it won't update the references to that resource
        # Check if there are any resources exactly like this
        siblings = self._package.resources.setdefault(self.checksum, [])

        if siblings:
            # If we're in the resource dir, and already have a filename that's different to our siblings, delete the original file
            # It probably means we're upgrading from pre-single-file-resources or someone has created the file to be imported inside the resource dir
            # We are assuming that it's not a file used by other resources...

            if not self._package.isLoading:

                newName = siblings[0]._storageName
                if oldPath.dirname(
                ) == self._package.resourceDir and self._storageName != newName:
                    oldPath.remove()
                self._storageName = newName
        else:
            if Path(oldPath).dirname() == self._package.resourceDir:
                log.debug(
                    u"StorageName=%s was already in self._package resources" %
                    self._storageName)
            else:
                filename = (self._package.resourceDir / oldPath.basename())
                storageName = self._fn2ascii(filename)
                if G.application.config.cutFileName == "1" and self._package != None:
                    if self._package.isChanged:
                        original = (self._package.resourceDir / storageName)
                        storageName = self.uniquePath(original, 0)
                    else:
                        storageName = (self._package.resourceDir /
                                       storageName).unique()
                else:
                    storageName = (self._package.resourceDir /
                                   storageName).unique()

                self._storageName = str(Path(storageName).basename())

                oldPath.copyfile(self.path)
        if not self._package.resources.get(self.checksum,
                                           []) or self._package.isLoading:
            # prevent doubling-up (as might occur when cleaning corrupt files)
            siblings.append(self)
Beispiel #54
0
 def testReferenceCounting(self):
     """
     Make 3 resources with different names but same md5, ensure they are reference counted properly
     """
     res1 = Path('my.resource1.bin')
     res2 = Path('my.resource2.bin')
     res3 = Path('my.resource3.bin')
     for res in (res1, res2, res3):
         res.write_bytes('SOME NICE DATA')
     res1md5 = res1.md5
     res4 = Path('tmp/my.resource1.bin')
     if not res4.dirname().exists():
         res4.dirname().makedirs()
     res4.write_bytes('SOME *DIFFERENT* DATA')
     res4md5 = res4.md5
     res1, res2, res3, res4 = map(lambda f: Resource(self.package, f),
                                  (res1, res2, res3, res4))
     assert res1.storageName == 'my.resource1.bin', res1.storageName
     assert res2.storageName == 'my.resource1.bin', res2.storageName
     assert res3.storageName == 'my.resource1.bin', res3.storageName
     assert res4.storageName == 'my.resource1.1.bin', res4.storageName
     assert res4.userName == 'my.resource1.bin', res4.userName
     assert len(self.package.resources) == 2
     assert len(self.package.resources[res1.path.md5]) == 3
     assert len(self.package.resources[res4.path.md5]) == 1
     assert self.package.resources[res4md5][0] is res4
     # Now start deleting things
     res4path = Path(res4.path)
     assert res4path.exists()
     res4.delete()
     assert not res4path.exists()
     assert res4md5 not in self.package.resources
     assert not res4path.exists()
     res1path = Path(res1.path)
     assert res1path.exists()
     res2.delete()
     assert res1path.exists()
     assert res2 not in self.package.resources[res1md5]
     res1.delete()
     assert res1path.exists()
     assert res1 not in self.package.resources[res1md5]
     res3.delete()
     assert res1md5 not in self.package.resources
     assert not res1path.exists()
Beispiel #55
0
    def export(self, package):
        """ 
        Export SCORM package
        """
        # First do the export to a temporary directory
        outputDir = TempDirPath()

        self.metadataType = package.exportMetadataType

        # copy the package's resource files
        package.resourceDir.copyfiles(outputDir)

        # copy the package's resource files, only non existant in outputDir
#        outputDirFiles = outputDir.files()
#        for rfile in package.resourceDir.files():
#            if rfile not in outputDirFiles:
#                rfile.copy(outputDir)

        # copy the package's resource files, only indexed in package.resources
#        for md5 in package.resources.values():
#            for resource in md5:
#                resource.path.copy(outputDir)

        # Export the package content
        # Import the Scorm Page class , if the secure mode is off.  If the style has it's own page class
        # use that, else use the default one.
        if self.styleSecureMode=="0":
            if (self.styleDir/"scormpage.py").exists():
                global ScormPage
                module = imp.load_source("ScormPage",self.styleDir/"scormpage.py")
                ScormPage = module.ScormPage


        self.pages = [ ScormPage("index", 1, package.root,
            scormType=self.scormType, metadataType=self.metadataType) ]

        self.generatePages(package.root, 2)
        uniquifyNames(self.pages)

        for page in self.pages:
            page.save(outputDir)
            if not self.hasForum:
                for idevice in page.node.idevices:
                    if hasattr(idevice, "isForum"):
                        if idevice.forum.lms.lms == "moodle":
                            self.hasForum = True
                            break

        # Create the manifest file
        manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType)
        manifest.save("imsmanifest.xml")
        if self.hasForum:
            manifest.save("discussionforum.xml")
        
        # Copy the style sheet files to the output dir
        styleFiles  = [self.styleDir/'..'/'base.css']
        styleFiles += [self.styleDir/'..'/'popup_bg.gif']
        # And with all the files of the style we avoid problems:
        styleFiles += self.styleDir.files("*.*")
        if self.scormType == "commoncartridge":
            for sf in styleFiles[:]:
                if sf.basename() not in manifest.dependencies:
                    styleFiles.remove(sf)
        self.styleDir.copylist(styleFiles, outputDir)
        
        # Copy the scripts
        dT = common.getExportDocType()
        if dT == "HTML5":
            jsFile = (self.scriptsDir/'exe_html5.js')
            jsFile.copyfile(outputDir/'exe_html5.js')
            
        # jQuery
        my_style = G.application.config.styleStore.getStyle(page.node.package.style)
        if my_style.hasValidConfig:
            if my_style.get_jquery() == True:
                jsFile = (self.scriptsDir/'exe_jquery.js')
                jsFile.copyfile(outputDir/'exe_jquery.js')
        else:
            jsFile = (self.scriptsDir/'exe_jquery.js')
            jsFile.copyfile(outputDir/'exe_jquery.js')
            
        if self.scormType == "commoncartridge":
            jsFile = (self.scriptsDir/'common.js')
            jsFile.copyfile(outputDir/'common.js')

        if self.scormType == "scorm2004" or self.scormType == "scorm1.2":
            self.scriptsDir.copylist(('SCORM_API_wrapper.js',
                                      'SCOFunctions.js', 
                                      'lernmodule_net.js',
                                      'lernmodule_net_custom.js',
                                      'common.js'), outputDir)     
        # about SCHEMAS:
        schemasDir = ""
        if self.scormType == "scorm1.2":
            schemasDir = self.schemasDir/"scorm1.2"
            schemasDir.copylist(('imscp_rootv1p1p2.xsd',
                                'imsmd_rootv1p2p1.xsd',
                                'adlcp_rootv1p2.xsd',
                                'lom.xsd',
                                'lomCustom.xsd',
                                'ims_xml.xsd'), outputDir)
        elif self.scormType == "scorm2004":
            schemasDir = self.schemasDir/"scorm2004"
            schemasDir.copylist(('adlcp_v1p3.xsd',
                                'adlnav_v1p3.xsd',
                                'adlseq_v1p3.xsd', 
                                'datatypes.dtd', 
                                'imscp_v1p1.xsd',
                                'imsssp_v1p0.xsd',
                                'imsss_v1p0.xsd',
                                'imsss_v1p0auxresource.xsd',
                                'imsss_v1p0control.xsd',
                                'imsss_v1p0delivery.xsd',
                                'imsmd_rootv1p2p1.xsd',
                                'imsss_v1p0limit.xsd',
                                'imsss_v1p0objective.xsd',
                                'imsss_v1p0random.xsd',
                                'imsss_v1p0rollup.xsd',
                                'imsss_v1p0seqrule.xsd',
                                'imsss_v1p0util.xsd',
                                'ims_xml.xsd',
                                'lom.xsd',
                                'lomCustom.xsd',
                                'xml.xsd',
                                'XMLSchema.dtd'), outputDir)
            try:
                import shutil, errno
                shutil.copytree(schemasDir/"common", outputDir/"common")
                shutil.copytree(schemasDir/"extend", outputDir/"extend")
                shutil.copytree(schemasDir/"unique", outputDir/"unique")
                shutil.copytree(schemasDir/"vocab", outputDir/"vocab")
            except OSError as exc:
                if exc.errno == errno.ENOTDIR:
                    shutil.copy(schemasDir, outputDir)
                else: raise

        # copy players for media idevices.                
        hasFlowplayer     = False
        hasMagnifier      = False
        hasXspfplayer     = False
        hasGallery        = False
        hasWikipedia      = False
        isBreak           = False
        hasInstructions   = False
        hasMediaelement   = False

        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasWikipedia and hasInstructions and hasMediaelement):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'mojomagnify.js' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True
                if not hasGallery:
                    hasGallery = common.ideviceHasGallery(idevice)
                if not hasWikipedia:
                    if 'WikipediaIdevice' == idevice.klass:
                        hasWikipedia = True
                if not hasInstructions:
                    if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                        hasInstructions = True
                if not hasMediaelement:
                    hasMediaelement = common.ideviceHasMediaelement(idevice)

        if hasFlowplayer:
            videofile = (self.templatesDir/'flowPlayer.swf')
            videofile.copyfile(outputDir/'flowPlayer.swf')
            controlsfile = (self.templatesDir/'flowplayer.controls.swf')
            controlsfile.copyfile(outputDir/'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir/'mojomagnify.js')
            videofile.copyfile(outputDir/'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir/'xspf_player.swf')
            videofile.copyfile(outputDir/'xspf_player.swf')
        if hasGallery:
            imageGalleryCSS = (self.cssDir/'exe_lightbox.css')
            imageGalleryCSS.copyfile(outputDir/'exe_lightbox.css') 
            imageGalleryJS = (self.scriptsDir/'exe_lightbox.js')
            imageGalleryJS.copyfile(outputDir/'exe_lightbox.js') 
            self.imagesDir.copylist(('exe_lightbox_close.png', 'exe_lightbox_loading.gif', 'exe_lightbox_next.png', 'exe_lightbox_prev.png'), outputDir)
        if hasWikipedia:
            wikipediaCSS = (self.cssDir/'exe_wikipedia.css')
            wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir)
            common.copyFileIfNotInStyle('stock-stop.png', self, outputDir)
        if hasMediaelement:
            mediaelement = (self.scriptsDir/'mediaelement')
            mediaelement.copyfiles(outputDir)
            if dT != "HTML5":
                jsFile = (self.scriptsDir/'exe_html5.js')

        if self.scormType == "scorm1.2" or self.scormType == "scorm2004":
            if package.license == "license GFDL":
                # include a copy of the GNU Free Documentation Licence
                (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html')
        
        if hasattr(package, 'scowsinglepage') and package.scowsinglepage:
            page = SinglePage("singlepage_index", 1, package.root)
            page.save(outputDir/"singlepage_index.html")
            # Incluide eXe's icon if the Style doesn't have one
            themePath = Path(G.application.config.stylesDir/package.style)
            themeFavicon = themePath.joinpath("favicon.ico")
            if not themeFavicon.exists():
                faviconFile = (self.imagesDir/'favicon.ico')
                faviconFile.copyfile(outputDir/'favicon.ico')
        if hasattr(package, 'scowwebsite') and package.scowwebsite:
            website = WebsiteExport(self.config, self.styleDir, outputDir, "website_")
            website.export(package)
            (self.styleDir/'nav.css').copyfile(outputDir/'nav.css')
            # Incluide eXe's icon if the Style doesn't have one
            themePath = Path(G.application.config.stylesDir/package.style)
            themeFavicon = themePath.joinpath("favicon.ico")
            if not themeFavicon.exists():
                faviconFile = (self.imagesDir/'favicon.ico')
                faviconFile.copyfile(outputDir/'favicon.ico')
        if hasattr(package, 'exportSource') and package.exportSource:
            (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd')
            (outputDir/'content.data').write_bytes(encodeObject(package))
            (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package))

        # Zip it up!
        self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir)
        # Clean up the temporary dir
        outputDir.rmtree()
Beispiel #56
0
class ScormExport(object):
    """
    Exports an eXe package as a SCORM package
    """
    def __init__(self, config, styleDir, filename, scormType):
        """ 
        Initialize
        'styleDir' is the directory from which we will copy our style sheets
        (and some gifs)
        """
        self.config = config
        self.imagesDir = config.webDir / "images"
        self.scriptsDir = config.webDir / "scripts"
        self.cssDir = config.webDir / "css"
        self.templatesDir = config.webDir / "templates"
        self.schemasDir = config.webDir / "schemas"
        self.styleDir = Path(styleDir)
        self.filename = Path(filename)
        self.pages = []
        self.hasForum = False
        self.scormType = scormType
        self.styleSecureMode = config.styleSecureMode

    def export(self, package):
        """ 
        Export SCORM package
        """
        # First do the export to a temporary directory
        outputDir = TempDirPath()

        self.metadataType = package.exportMetadataType

        # copy the package's resource files
        package.resourceDir.copyfiles(outputDir)

        # copy the package's resource files, only non existant in outputDir
        #        outputDirFiles = outputDir.files()
        #        for rfile in package.resourceDir.files():
        #            if rfile not in outputDirFiles:
        #                rfile.copy(outputDir)

        # copy the package's resource files, only indexed in package.resources
        #        for md5 in package.resources.values():
        #            for resource in md5:
        #                resource.path.copy(outputDir)

        # Export the package content
        # Import the Scorm Page class , if the secure mode is off.  If the style has it's own page class
        # use that, else use the default one.
        if self.styleSecureMode == "0":
            if (self.styleDir / "scormpage.py").exists():
                global ScormPage
                module = imp.load_source("ScormPage",
                                         self.styleDir / "scormpage.py")
                ScormPage = module.ScormPage

        self.pages = [
            ScormPage("index",
                      1,
                      package.root,
                      scormType=self.scormType,
                      metadataType=self.metadataType)
        ]

        self.generatePages(package.root, 2)
        uniquifyNames(self.pages)

        for page in self.pages:
            page.save(outputDir)
            if not self.hasForum:
                for idevice in page.node.idevices:
                    if hasattr(idevice, "isForum"):
                        if idevice.forum.lms.lms == "moodle":
                            self.hasForum = True
                            break

        # Create the manifest file
        manifest = Manifest(self.config, outputDir, package, self.pages,
                            self.scormType, self.metadataType)
        manifest.save("imsmanifest.xml")
        if self.hasForum:
            manifest.save("discussionforum.xml")

        # Copy the style sheet files to the output dir

        styleFiles = [self.styleDir / '..' / 'popup_bg.gif']
        # And with all the files of the style we avoid problems:
        styleFiles += self.styleDir.files("*.*")
        if self.scormType == "commoncartridge":
            for sf in styleFiles[:]:
                if sf.basename() not in manifest.dependencies:
                    styleFiles.remove(sf)
        self.styleDir.copylist(styleFiles, outputDir)

        listCSSFiles = getFilesCSSToMinify('scorm', self.styleDir)
        exportMinFileCSS(listCSSFiles, outputDir)

        # Copy the scripts

        dT = common.getExportDocType()
        if dT == "HTML5":
            #listFiles+=[self.scriptsDir/'exe_html5.js']
            #listOutFiles+=[outputDir/'exe_html5.js']
            jsFile = (self.scriptsDir / 'exe_html5.js')
            jsFile.copyfile(outputDir / 'exe_html5.js')

        # jQuery
        my_style = G.application.config.styleStore.getStyle(
            page.node.package.style)
        if my_style.hasValidConfig:
            if my_style.get_jquery() == True:
                #listFiles+=[self.scriptsDir/'exe_jquery.js']
                #listOutFiles+=[outputDir/'exe_jquery.js']
                jsFile = (self.scriptsDir / 'exe_jquery.js')
                jsFile.copyfile(outputDir / 'exe_jquery.js')
        else:
            #listFiles+=[self.scriptsDir/'exe_jquery.js']
            #listOutFiles+=[outputDir/'exe_jquery.js']
            jsFile = (self.scriptsDir / 'exe_jquery.js')
            jsFile.copyfile(outputDir / 'exe_jquery.js')

        if self.scormType == "commoncartridge" or self.scormType == "scorm2004" or self.scormType == "scorm1.2":
            listFiles = getFilesJSToMinify('scorm', self.scriptsDir)

        exportMinFileJS(listFiles, outputDir)

        if self.scormType == "scorm2004" or self.scormType == "scorm1.2":
            self.scriptsDir.copylist(
                ('SCORM_API_wrapper.js', 'SCOFunctions.js'), outputDir)

        # about SCHEMAS:
        schemasDir = ""
        if self.scormType == "scorm1.2":
            schemasDir = self.schemasDir / "scorm1.2"
            schemasDir.copylist(('imscp_rootv1p1p2.xsd',
                                 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd',
                                 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'),
                                outputDir)
        elif self.scormType == "scorm2004":
            schemasDir = self.schemasDir / "scorm2004"
            schemasDir.copylist(
                ('adlcp_v1p3.xsd', 'adlnav_v1p3.xsd', 'adlseq_v1p3.xsd',
                 'datatypes.dtd', 'imscp_v1p1.xsd', 'imsssp_v1p0.xsd',
                 'imsss_v1p0.xsd', 'imsss_v1p0auxresource.xsd',
                 'imsss_v1p0control.xsd', 'imsss_v1p0delivery.xsd',
                 'imsmd_rootv1p2p1.xsd', 'imsss_v1p0limit.xsd',
                 'imsss_v1p0objective.xsd', 'imsss_v1p0random.xsd',
                 'imsss_v1p0rollup.xsd', 'imsss_v1p0seqrule.xsd',
                 'imsss_v1p0util.xsd', 'ims_xml.xsd', 'lom.xsd',
                 'lomCustom.xsd', 'xml.xsd', 'XMLSchema.dtd'), outputDir)
            try:
                import shutil, errno
                shutil.copytree(schemasDir / "common", outputDir / "common")
                shutil.copytree(schemasDir / "extend", outputDir / "extend")
                shutil.copytree(schemasDir / "unique", outputDir / "unique")
                shutil.copytree(schemasDir / "vocab", outputDir / "vocab")
            except OSError as exc:
                if exc.errno == errno.ENOTDIR:
                    shutil.copy(schemasDir, outputDir)
                else:
                    raise

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        hasGallery = False
        hasFX = False
        hasSH = False
        hasGames = False
        hasWikipedia = False
        isBreak = False
        hasInstructions = False
        hasMediaelement = False
        hasTooltips = False

        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer
                        and hasGallery and hasFX and hasSH and hasGames
                        and hasWikipedia and hasInstructions
                        and hasMediaelement and hasTooltips):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'mojomagnify.js' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True
                if not hasGallery:
                    hasGallery = common.ideviceHasGallery(idevice)
                if not hasFX:
                    hasFX = common.ideviceHasFX(idevice)
                if not hasSH:
                    hasSH = common.ideviceHasSH(idevice)
                if not hasGames:
                    hasGames = common.ideviceHasGames(idevice)
                if not hasWikipedia:
                    if 'WikipediaIdevice' == idevice.klass:
                        hasWikipedia = True
                if not hasInstructions:
                    if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                        hasInstructions = True
                if not hasMediaelement:
                    hasMediaelement = common.ideviceHasMediaelement(idevice)
                if not hasTooltips:
                    hasTooltips = common.ideviceHasTooltips(idevice)

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(outputDir / 'flowPlayer.swf')
            controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
            controlsfile.copyfile(outputDir / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'mojomagnify.js')
            videofile.copyfile(outputDir / 'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(outputDir / 'xspf_player.swf')
        if hasGallery:
            exeLightbox = (self.scriptsDir / 'exe_lightbox')
            exeLightbox.copyfiles(outputDir)
        if hasFX:
            exeEffects = (self.scriptsDir / 'exe_effects')
            exeEffects.copyfiles(outputDir)
        if hasSH:
            exeSH = (self.scriptsDir / 'exe_highlighter')
            exeSH.copyfiles(outputDir)
        if hasGames:
            exeGames = (self.scriptsDir / 'exe_games')
            exeGames.copyfiles(outputDir)
        if hasWikipedia:
            wikipediaCSS = (self.cssDir / 'exe_wikipedia.css')
            wikipediaCSS.copyfile(outputDir / 'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self,
                                        outputDir)
            common.copyFileIfNotInStyle('stock-stop.png', self, outputDir)
        if hasMediaelement:
            mediaelement = (self.scriptsDir / 'mediaelement')
            mediaelement.copyfiles(outputDir)
            if dT != "HTML5":
                jsFile = (self.scriptsDir / 'exe_html5.js')
        if hasTooltips:
            exe_tooltips = (self.scriptsDir / 'exe_tooltips')
            exe_tooltips.copyfiles(outputDir)

        if self.scormType == "scorm1.2" or self.scormType == "scorm2004":
            if package.license == "license GFDL":
                # include a copy of the GNU Free Documentation Licence
                (self.templatesDir / 'fdl.html').copyfile(outputDir /
                                                          'fdl.html')

        if hasattr(package, 'scowsinglepage') and package.scowsinglepage:
            page = SinglePage("singlepage_index", 1, package.root)
            page.save(outputDir / "singlepage_index.html")
            # Incluide eXe's icon if the Style doesn't have one
            themePath = Path(G.application.config.stylesDir / package.style)
            themeFavicon = themePath.joinpath("favicon.ico")
            if not themeFavicon.exists():
                faviconFile = (self.imagesDir / 'favicon.ico')
                faviconFile.copyfile(outputDir / 'favicon.ico')
        if hasattr(package, 'scowwebsite') and package.scowwebsite:
            website = WebsiteExport(self.config, self.styleDir, outputDir,
                                    "website_")
            website.export(package)
            (self.styleDir / 'nav.css').copyfile(outputDir / 'nav.css')
            # Incluide eXe's icon if the Style doesn't have one
            themePath = Path(G.application.config.stylesDir / package.style)
            themeFavicon = themePath.joinpath("favicon.ico")
            if not themeFavicon.exists():
                faviconFile = (self.imagesDir / 'favicon.ico')
                faviconFile.copyfile(outputDir / 'favicon.ico')
        if hasattr(package, 'exportSource') and package.exportSource:
            (G.application.config.webDir / 'templates' /
             'content.xsd').copyfile(outputDir / 'content.xsd')
            (outputDir / 'content.data').write_bytes(encodeObject(package))
            (outputDir / 'contentv3.xml').write_bytes(
                encodeObjectToXML(package))

        # Zip it up!
        self.filename.safeSave(
            self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'),
            outputDir)
        # Clean up the temporary dir
        outputDir.rmtree()

    def doZip(self, fileObj, outputDir):
        """
        Actually does the zipping of the file. Called by 'Path.safeSave'
        """
        # Zip up the scorm package
        zipped = ZipFile(fileObj, "w")
        ## old method: only files could be copied:
        # for scormFile in outputDir.files():
        #    zipped.write(scormFile,
        #                 scormFile.basename().encode('utf8'),
        #                  ZIP_DEFLATED)
        ## but some folders must be included also, so:
        outputlen = len(outputDir) + 1
        for base, dirs, files in os.walk(outputDir):
            for file in files:
                fn = os.path.join(base, file)
                zipped.write(fn, fn[outputlen:].encode('utf8'), ZIP_DEFLATED)
        #
        zipped.close()

    def generatePages(self, node, depth):
        """
        Recursive function for exporting a node.
        'node' is the node that we are making a page for
        'depth' is the number of ancestors that the page has +1 (ie. root is 1)
        """
        for child in node.children:
            pageName = child.titleShort.lower().replace(" ", "_")
            pageName = re.sub(r"\W", "", pageName)
            if not pageName:
                pageName = "__"

            page = ScormPage(pageName,
                             depth,
                             child,
                             scormType=self.scormType,
                             metadataType=self.metadataType)

            self.pages.append(page)
            self.generatePages(child, depth + 1)
Beispiel #57
0
    def compruebaReproductores(self, node):
        """
        Comprobamos si hay que meter algun reproductor
        """

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        hasGallery = False
        hasFX = False
        hasSH = False
        hasGames = False
        hasElpLink = False
        hasWikipedia = False
        hasInstructions = False
        hasMediaelement = False
        hasTooltips = False
        hasABCMusic = False
        listIdevicesFiles = []

        for idevice in node.idevices:
            if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery
                    and hasFX and hasSH and hasGames and hasElpLink
                    and hasWikipedia and hasInstructions and hasMediaelement
                    and hasTooltips and hasABCMusic):
                break
            if not hasFlowplayer:
                if 'flowPlayer.swf' in idevice.systemResources:
                    hasFlowplayer = True
            if not hasMagnifier:
                if 'mojomagnify.js' in idevice.systemResources:
                    hasMagnifier = True
            if not hasXspfplayer:
                if 'xspf_player.swf' in idevice.systemResources:
                    hasXspfplayer = True
            if not hasGallery:
                hasGallery = common.ideviceHasGallery(idevice)
            if not hasFX:
                hasFX = common.ideviceHasFX(idevice)
            if not hasSH:
                hasSH = common.ideviceHasSH(idevice)
            if not hasGames:
                hasGames = common.ideviceHasGames(idevice)
            if not hasElpLink:
                hasElpLink = common.ideviceHasElpLink(idevice,
                                                      self.page.node.package)
            if not hasWikipedia:
                if 'WikipediaIdevice' == idevice.klass:
                    hasWikipedia = True
            if not hasInstructions:
                if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                    hasInstructions = True
            if not hasMediaelement:
                hasMediaelement = common.ideviceHasMediaelement(idevice)
            if not hasTooltips:
                hasTooltips = common.ideviceHasTooltips(idevice)
            if not hasABCMusic:
                hasABCMusic = common.ideviceHasABCMusic(idevice)
            if hasattr(idevice, "_iDeviceDir"):
                listIdevicesFiles.append(
                    (idevice.get_jsidevice_dir() / 'export'))

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(self.outputDir / 'flowPlayer.swf')
            controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
            controlsfile.copyfile(self.outputDir / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'mojomagnify.js')
            videofile.copyfile(self.outputDir / 'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(self.outputDir / 'xspf_player.swf')
        if hasGallery:
            exeLightbox = (self.scriptsDir / 'exe_lightbox')
            exeLightbox.copyfiles(self.outputDir)
        if hasFX:
            exeEffects = (self.scriptsDir / 'exe_effects')
            exeEffects.copyfiles(self.outputDir)
        if hasSH:
            exeSH = (self.scriptsDir / 'exe_highlighter')
            exeSH.copyfiles(self.outputDir)
        if hasGames:
            exeGames = (self.scriptsDir / 'exe_games')
            exeGames.copyfiles(self.outputDir)
            # Add game js string to common_i18n
            langGameFile = open(self.outputDir + '/common_i18n.js', "a")
            langGameFile.write(common.getGamesJavaScriptStrings(False))
            langGameFile.close()
        if hasElpLink or self.page.node.package.get_exportElp():
            # Export the elp file
            currentPackagePath = Path(self.page.node.package.filename)
            currentPackagePath.copyfile(self.outputDir /
                                        self.page.node.package.name + '.elp')
        if hasWikipedia:
            wikipediaCSS = (self.cssDir / 'exe_wikipedia.css')
            wikipediaCSS.copyfile(self.outputDir / 'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self,
                                        self.outputDir)
            common.copyFileIfNotInStyle('stock-stop.png', self, self.outputDir)
        if hasMediaelement:
            mediaelement = (self.scriptsDir / 'mediaelement')
            mediaelement.copyfiles(self.outputDir)
            dT = common.getExportDocType()
            if dT != "HTML5":
                jsFile = (self.scriptsDir / 'exe_html5.js')
                jsFile.copyfile(self.outputDir / 'exe_html5.js')
        if hasTooltips:
            exe_tooltips = (self.scriptsDir / 'exe_tooltips')
            exe_tooltips.copyfiles(self.outputDir)
        if hasABCMusic:
            pluginScripts = (self.scriptsDir /
                             'tinymce_4/js/tinymce/plugins/abcmusic/export')
            pluginScripts.copyfiles(self.outputDir)

        for child in node.children:
            self.compruebaReproductores(child)

        common.exportJavaScriptIdevicesFiles(node.idevices, self.outputDir)
Beispiel #58
0
class SinglePageExport(object):
    """
    SinglePageExport will export a package as a website of HTML pages
    """
    def __init__(self, stylesDir, outputDir, imagesDir, scriptsDir, cssDir,
                 templatesDir):
        """
        'stylesDir' is the directory where we can copy the stylesheets from
        'outputDir' is the directory that will be [over]written
        with the website
        """
        self.html = ""
        self.style = None
        self.name = None
        self.stylesDir = Path(stylesDir)
        self.outputDir = Path(outputDir)
        self.imagesDir = Path(imagesDir)
        self.scriptsDir = Path(scriptsDir)
        self.cssDir = Path(cssDir)
        self.templatesDir = Path(templatesDir)
        self.page = None

        # Create the output dir if it doesn't already exist
        if not self.outputDir.exists():
            self.outputDir.mkdir()

    def export(self, package, for_print=0):
        """
        Export web site
        Cleans up the previous packages pages and performs the export
        """
        self.style = package.style

        self.page = SinglePage("index", 1, package.root)
        ext = 'html'
        if G.application.config.cutFileName == "1":
            ext = 'htm'

        self.page.save(self.outputDir / "index" + '.' + ext, for_print)
        if hasattr(package,
                   'exportSource') and package.exportSource and not for_print:
            (G.application.config.webDir / 'templates' /
             'content.xsd').copyfile(self.outputDir / 'content.xsd')
            (self.outputDir / 'content.data').write_bytes(
                encodeObject(package))
            (self.outputDir / 'contentv3.xml').write_bytes(
                encodeObjectToXML(package))

        self.copyFiles(package)

    def copyFiles(self, package):
        """
        Copy all the files used by the website.
        """
        # Copy the style files to the output dir
        # But not nav.css
        if os.path.isdir(self.stylesDir):
            styleFiles = [self.stylesDir / '..' / 'popup_bg.gif']
            styleFiles += self.stylesDir.files("*.*")
            if "nav.css" in styleFiles:
                styleFiles.remove("nav.css")
            self.stylesDir.copylist(styleFiles, self.outputDir)

        # copy the package's resource files
        for resourceFile in package.resourceDir.walkfiles():
            file = package.resourceDir.relpathto(resourceFile)

            if ("/" in file):
                Dir = Path(self.outputDir / file[:file.rindex("/")])

                if not Dir.exists():
                    Dir.makedirs()

                resourceFile.copy(self.outputDir / Dir)
            else:
                resourceFile.copy(self.outputDir)

        listCSSFiles = getFilesCSSToMinify('singlepage', self.stylesDir)
        exportMinFileCSS(listCSSFiles, self.outputDir)

        # copy script files.
        my_style = G.application.config.styleStore.getStyle(package.style)

        # jQuery
        if my_style.hasValidConfig():
            if my_style.get_jquery() == True:
                jsFile = (self.scriptsDir / 'exe_jquery.js')
                jsFile.copyfile(self.outputDir / 'exe_jquery.js')
        else:
            jsFile = (self.scriptsDir / 'exe_jquery.js')
            jsFile.copyfile(self.outputDir / 'exe_jquery.js')

        dT = common.getExportDocType()
        if dT == "HTML5":
            jsFile = (self.scriptsDir / 'exe_html5.js')
            jsFile.copyfile(self.outputDir / 'exe_html5.js')

        # Minify common.js file
        listFiles = getFilesJSToMinify('singlepage', self.scriptsDir)
        exportMinFileJS(listFiles, self.outputDir)

        # Create lang file
        langFile = open(self.outputDir + '/common_i18n.js', "w")
        langFile.write(common.getJavaScriptStrings(False))
        langFile.close()

        # Incluide eXe's icon if the Style doesn't have one
        themePath = Path(G.application.config.stylesDir / package.style)
        themeFavicon = themePath.joinpath("favicon.ico")
        if not themeFavicon.exists():
            faviconFile = (self.imagesDir / 'favicon.ico')
            faviconFile.copyfile(self.outputDir / 'favicon.ico')

        #JR Metemos los reproductores necesarios
        self.compruebaReproductores(self.page.node)

        if package.license == "license GFDL":
            # include a copy of the GNU Free Documentation Licence
            ext = 'html'
            if G.application.config.cutFileName == "1":
                ext = 'htm'
            (self.templatesDir / 'fdl' + '.' +
             ext).copyfile(self.outputDir / 'fdl' + '.' + ext)

    def compruebaReproductores(self, node):
        """
        Comprobamos si hay que meter algun reproductor
        """

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        hasGallery = False
        hasFX = False
        hasSH = False
        hasGames = False
        hasElpLink = False
        hasWikipedia = False
        hasInstructions = False
        hasMediaelement = False
        hasTooltips = False
        hasABCMusic = False
        listIdevicesFiles = []

        for idevice in node.idevices:
            if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery
                    and hasFX and hasSH and hasGames and hasElpLink
                    and hasWikipedia and hasInstructions and hasMediaelement
                    and hasTooltips and hasABCMusic):
                break
            if not hasFlowplayer:
                if 'flowPlayer.swf' in idevice.systemResources:
                    hasFlowplayer = True
            if not hasMagnifier:
                if 'mojomagnify.js' in idevice.systemResources:
                    hasMagnifier = True
            if not hasXspfplayer:
                if 'xspf_player.swf' in idevice.systemResources:
                    hasXspfplayer = True
            if not hasGallery:
                hasGallery = common.ideviceHasGallery(idevice)
            if not hasFX:
                hasFX = common.ideviceHasFX(idevice)
            if not hasSH:
                hasSH = common.ideviceHasSH(idevice)
            if not hasGames:
                hasGames = common.ideviceHasGames(idevice)
            if not hasElpLink:
                hasElpLink = common.ideviceHasElpLink(idevice,
                                                      self.page.node.package)
            if not hasWikipedia:
                if 'WikipediaIdevice' == idevice.klass:
                    hasWikipedia = True
            if not hasInstructions:
                if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                    hasInstructions = True
            if not hasMediaelement:
                hasMediaelement = common.ideviceHasMediaelement(idevice)
            if not hasTooltips:
                hasTooltips = common.ideviceHasTooltips(idevice)
            if not hasABCMusic:
                hasABCMusic = common.ideviceHasABCMusic(idevice)
            if hasattr(idevice, "_iDeviceDir"):
                listIdevicesFiles.append(
                    (idevice.get_jsidevice_dir() / 'export'))

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(self.outputDir / 'flowPlayer.swf')
            controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
            controlsfile.copyfile(self.outputDir / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'mojomagnify.js')
            videofile.copyfile(self.outputDir / 'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(self.outputDir / 'xspf_player.swf')
        if hasGallery:
            exeLightbox = (self.scriptsDir / 'exe_lightbox')
            exeLightbox.copyfiles(self.outputDir)
        if hasFX:
            exeEffects = (self.scriptsDir / 'exe_effects')
            exeEffects.copyfiles(self.outputDir)
        if hasSH:
            exeSH = (self.scriptsDir / 'exe_highlighter')
            exeSH.copyfiles(self.outputDir)
        if hasGames:
            exeGames = (self.scriptsDir / 'exe_games')
            exeGames.copyfiles(self.outputDir)
            # Add game js string to common_i18n
            langGameFile = open(self.outputDir + '/common_i18n.js', "a")
            langGameFile.write(common.getGamesJavaScriptStrings(False))
            langGameFile.close()
        if hasElpLink or self.page.node.package.get_exportElp():
            # Export the elp file
            currentPackagePath = Path(self.page.node.package.filename)
            currentPackagePath.copyfile(self.outputDir /
                                        self.page.node.package.name + '.elp')
        if hasWikipedia:
            wikipediaCSS = (self.cssDir / 'exe_wikipedia.css')
            wikipediaCSS.copyfile(self.outputDir / 'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self,
                                        self.outputDir)
            common.copyFileIfNotInStyle('stock-stop.png', self, self.outputDir)
        if hasMediaelement:
            mediaelement = (self.scriptsDir / 'mediaelement')
            mediaelement.copyfiles(self.outputDir)
            dT = common.getExportDocType()
            if dT != "HTML5":
                jsFile = (self.scriptsDir / 'exe_html5.js')
                jsFile.copyfile(self.outputDir / 'exe_html5.js')
        if hasTooltips:
            exe_tooltips = (self.scriptsDir / 'exe_tooltips')
            exe_tooltips.copyfiles(self.outputDir)
        if hasABCMusic:
            pluginScripts = (self.scriptsDir /
                             'tinymce_4/js/tinymce/plugins/abcmusic/export')
            pluginScripts.copyfiles(self.outputDir)

        for child in node.children:
            self.compruebaReproductores(child)

        common.exportJavaScriptIdevicesFiles(node.idevices, self.outputDir)

    def hasUncutResources(self):
        """
        Check if any of the resources in the exported package has an uncut filename
        """
        for idevice in self.page.node.idevices:
            for resource in idevice.userResources:
                if type(resource) == Resource and len(
                        resource.storageName) > 12:
                    return True
        return False
Beispiel #59
0
class WebsiteExport(object):
    """
    WebsiteExport will export a package as a website of HTML pages
    """
    def __init__(self, config, styleDir, filename, prefix="", report=False):
        """
        'stylesDir' is the directory where we can copy the stylesheets from
        'outputDir' is the directory that will be [over]written
        with the website
        """
        self.config = config
        self.imagesDir = config.webDir / "images"
        self.scriptsDir = config.webDir / "scripts"
        self.cssDir = config.webDir / "css"
        self.templatesDir = config.webDir / "templates"
        self.stylesDir = Path(styleDir)
        self.filename = Path(filename)
        self.pages = []
        self.prefix = prefix
        self.report = report
        self.styleSecureMode = config.styleSecureMode

    def exportZip(self, package):
        """ 
        Export web site
        Cleans up the previous packages pages and performs the export
        """

        outputDir = TempDirPath()

        # Import the Website Page class , if the secure mode is off.  If the style has it's own page class
        # use that, else use the default one.
        if self.styleSecureMode == "0":
            if (self.stylesDir / "websitepage.py").exists():
                global WebsitePage
                module = imp.load_source("websitepage",
                                         self.stylesDir / "websitepage.py")
                WebsitePage = module.WebsitePage

        self.pages = [WebsitePage("index", 0, package.root)]
        self.generatePages(package.root, 1)
        uniquifyNames(self.pages)

        prevPage = None
        thisPage = self.pages[0]

        for nextPage in self.pages[1:]:
            thisPage.save(outputDir, prevPage, nextPage, self.pages)
            prevPage = thisPage
            thisPage = nextPage

        thisPage.save(outputDir, prevPage, None, self.pages)
        self.copyFiles(package, outputDir)
        # Zip up the website package
        self.filename.safeSave(
            self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'),
            outputDir)
        # Clean up the temporary dir
        outputDir.rmtree()

    def doZip(self, fileObj, outputDir):
        """
        Actually saves the zip data. Called by 'Path.safeSave'
        """
        zipped = ZipFile(fileObj, "w")
        for scormFile in outputDir.walkfiles():
            zipped.write(scormFile, outputDir.relpathto(scormFile),
                         ZIP_DEFLATED)
        zipped.close()

    def appendPageReport(self, page, package):
        ext = 'html'
        if G.application.config.cutFileName == "1":
            ext = 'htm'
        if not page.node.idevices:
            self.report += u'"%s","%s",%d,"%s",,,,,,\n' % (
                package.filename, page.node.title, page.depth,
                page.name + '.' + ext)
        for idevice in page.node.idevices:
            if not idevice.userResources:
                self.report += u'"%s","%s",%d,"%s","%s","%s",,,,\n' % (
                    package.filename, page.node.title, page.depth,
                    page.name + '.' + ext, idevice.klass, idevice.title)
            for resource in idevice.userResources:
                if type(resource) == Resource:
                    self.report += u'"%s","%s",%d,"%s","%s","%s","%s","%s","%s","%s"\n' % (
                        package.filename, page.node.title, page.depth,
                        page.name + '.' + ext, idevice.klass, idevice.title,
                        resource.storageName, resource.userName, resource.path,
                        resource.checksum)
                else:
                    self.report += u'"%s",%d,"%s","%s","%s","%s",,,\n' % (
                        package.filename, page.node.title, page.depth,
                        page.name + '.' + ext, idevice.klass, idevice.title,
                        resource)

    def export(self, package):
        """ 
        Export web site
        Cleans up the previous packages pages and performs the export
        """
        if not self.report:
            outputDir = self.filename
            if not outputDir.exists():
                outputDir.mkdir()

        # Import the Website Page class.  If the style has it's own page class
        # use that, else use the default one.
        if (self.stylesDir / "websitepage.py").exists():
            global WebsitePage
            module = imp.load_source("websitepage",
                                     self.stylesDir / "websitepage.py")
            WebsitePage = module.WebsitePage

        self.pages = [WebsitePage(self.prefix + "index", 0, package.root)]
        self.generatePages(package.root, 1)
        uniquifyNames(self.pages)

        prevPage = None
        thisPage = self.pages[0]
        if self.report:
            self.report = u'"%s","%s","%s","%s","%s","%s","%s","%s","%s","%s"\n' % (
                'File', 'Page Name', 'Level', 'Page File Name', 'Idevice Type',
                'Idevice Title', 'Resource File Name', 'Resource User Name',
                'Resource Path', 'Resource Checksum')
            self.appendPageReport(thisPage, package)

        for nextPage in self.pages[1:]:
            if self.report:
                self.appendPageReport(nextPage, package)
            else:
                thisPage.save(outputDir, prevPage, nextPage, self.pages)
            prevPage = thisPage
            thisPage = nextPage

        if not self.report:
            thisPage.save(outputDir, prevPage, None, self.pages)

            if self.prefix == "":
                self.copyFiles(package, outputDir)

            return outputDir

        else:
            self.filename.write_text(self.report, 'utf-8')

    def copyFiles(self, package, outputDir):
        """
        Copy all the files used by the website.
        """

        if os.path.isdir(self.stylesDir):
            # Copy the style files to the output dir
            styleFiles = [self.stylesDir / '..' / 'popup_bg.gif']
            styleFiles += self.stylesDir.files("*.*")
            self.stylesDir.copylist(styleFiles, outputDir)

        # copy the package's resource files
        for resourceFile in package.resourceDir.walkfiles():
            file = package.resourceDir.relpathto(resourceFile)

            if ("/" in file):
                Dir = Path(outputDir / file[:file.rindex("/")])

                if not Dir.exists():
                    Dir.makedirs()

                resourceFile.copy(outputDir / Dir)
            else:
                resourceFile.copy(outputDir)

        listCSSFiles = getFilesCSSToMinify('website', self.stylesDir)
        exportMinFileCSS(listCSSFiles, outputDir)

        # copy script files.
        my_style = G.application.config.styleStore.getStyle(package.style)
        # jQuery
        listFiles = []
        listOutFiles = []
        if my_style.hasValidConfig:
            if my_style.get_jquery() == True:
                jsFile = (self.scriptsDir / 'exe_jquery.js')
                jsFile.copyfile(outputDir / 'exe_jquery.js')
        else:
            listFiles += [self.scriptsDir / 'exe_jquery.js']
            listOutFiles += [outputDir / 'exe_jquery.js']

        # Minify common.js file
        listFiles = getFilesJSToMinify('website', self.scriptsDir)
        exportMinFileJS(listFiles, outputDir)

        # Create lang file
        langFile = open(outputDir + '/common_i18n.js', "w")
        langFile.write(common.getJavaScriptStrings(False))
        langFile.close()
        #dT = common.getExportDocType()
        dT = common.getExportDocType()
        if dT == "HTML5":
            jsFile = (self.scriptsDir / 'exe_html5.js')
            jsFile.copyfile(outputDir / 'exe_html5.js')

        # Incluide eXe's icon if the Style doesn't have one
        themePath = Path(G.application.config.stylesDir / package.style)
        themeFavicon = themePath.joinpath("favicon.ico")
        if not themeFavicon.exists():
            faviconFile = (self.imagesDir / 'favicon.ico')
            faviconFile.copyfile(outputDir / 'favicon.ico')

        # copy players for media idevices.
        hasFlowplayer = False
        hasMagnifier = False
        hasXspfplayer = False
        hasGallery = False
        hasFX = False
        hasSH = False
        hasGames = False
        hasWikipedia = False
        isBreak = False
        hasInstructions = False
        hasMediaelement = False
        hasTooltips = False
        hasABCMusic = False
        listIdevicesFiles = []

        for page in self.pages:
            if isBreak:
                break
            for idevice in page.node.idevices:
                if (hasFlowplayer and hasMagnifier and hasXspfplayer
                        and hasGallery and hasFX and hasSH and hasGames
                        and hasWikipedia and hasInstructions
                        and hasMediaelement and hasTooltips and hasABCMusic):
                    isBreak = True
                    break
                if not hasFlowplayer:
                    if 'flowPlayer.swf' in idevice.systemResources:
                        hasFlowplayer = True
                if not hasMagnifier:
                    if 'mojomagnify.js' in idevice.systemResources:
                        hasMagnifier = True
                if not hasXspfplayer:
                    if 'xspf_player.swf' in idevice.systemResources:
                        hasXspfplayer = True
                if not hasGallery:
                    hasGallery = common.ideviceHasGallery(idevice)
                if not hasFX:
                    hasFX = common.ideviceHasFX(idevice)
                if not hasSH:
                    hasSH = common.ideviceHasSH(idevice)
                if not hasGames:
                    hasGames = common.ideviceHasGames(idevice)
                if not hasWikipedia:
                    if 'WikipediaIdevice' == idevice.klass:
                        hasWikipedia = True
                if not hasInstructions:
                    if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass:
                        hasInstructions = True
                if not hasMediaelement:
                    hasMediaelement = common.ideviceHasMediaelement(idevice)
                if not hasTooltips:
                    hasTooltips = common.ideviceHasTooltips(idevice)
                if not hasABCMusic:
                    hasABCMusic = common.ideviceHasABCMusic(idevice)
                if hasattr(idevice, "_iDeviceDir"):
                    listIdevicesFiles.append(
                        (Path(idevice._iDeviceDir) / 'export'))

            common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir)

        if hasFlowplayer:
            videofile = (self.templatesDir / 'flowPlayer.swf')
            videofile.copyfile(outputDir / 'flowPlayer.swf')
            controlsfile = (self.templatesDir / 'flowplayer.controls.swf')
            controlsfile.copyfile(outputDir / 'flowplayer.controls.swf')
        if hasMagnifier:
            videofile = (self.templatesDir / 'mojomagnify.js')
            videofile.copyfile(outputDir / 'mojomagnify.js')
        if hasXspfplayer:
            videofile = (self.templatesDir / 'xspf_player.swf')
            videofile.copyfile(outputDir / 'xspf_player.swf')
        if hasGallery:
            exeLightbox = (self.scriptsDir / 'exe_lightbox')
            exeLightbox.copyfiles(outputDir)
        if hasFX:
            exeEffects = (self.scriptsDir / 'exe_effects')
            exeEffects.copyfiles(outputDir)
        if hasSH:
            exeSH = (self.scriptsDir / 'exe_highlighter')
            exeSH.copyfiles(outputDir)
        if hasGames:
            exeGames = (self.scriptsDir / 'exe_games')
            exeGames.copyfiles(outputDir)
            # Add game js string to common_i18n
            langGameFile = open(outputDir + '/common_i18n.js', "a")
            langGameFile.write(common.getGamesJavaScriptStrings(False))
            langGameFile.close()
        if hasABCMusic:
            pluginScripts = (self.scriptsDir /
                             'tinymce_4/js/tinymce/plugins/abcmusic/export')
            pluginScripts.copyfiles(outputDir)
        if hasWikipedia:
            wikipediaCSS = (self.cssDir / 'exe_wikipedia.css')
            wikipediaCSS.copyfile(outputDir / 'exe_wikipedia.css')
        if hasInstructions:
            common.copyFileIfNotInStyle('panel-amusements.png', self,
                                        outputDir)
            common.copyFileIfNotInStyle('stock-stop.png', self, outputDir)
        if hasMediaelement:
            mediaelement = (self.scriptsDir / 'mediaelement')
            mediaelement.copyfiles(outputDir)
            dT = common.getExportDocType()
            if dT != "HTML5":
                jsFile = (self.scriptsDir / 'exe_html5.js')
                jsFile.copyfile(outputDir / 'exe_html5.js')
        if hasTooltips:
            exe_tooltips = (self.scriptsDir / 'exe_tooltips')
            exe_tooltips.copyfiles(outputDir)

        if hasattr(package, 'exportSource') and package.exportSource:
            (G.application.config.webDir / 'templates' /
             'content.xsd').copyfile(outputDir / 'content.xsd')
            (outputDir / 'content.data').write_bytes(encodeObject(package))
            (outputDir / 'contentv3.xml').write_bytes(
                encodeObjectToXML(package))
        ext = 'html'
        if G.application.config.cutFileName == "1":
            ext = 'htm'
        if package.license == "license GFDL":
            # include a copy of the GNU Free Documentation Licence
            (self.templatesDir / 'fdl' + '.' +
             ext).copyfile(outputDir / 'fdl' + '.' + ext)

    def generatePages(self, node, depth):
        """
        Recursively generate pages and store in pages member variable
        for retrieving later
        """
        for child in node.children:
            # assure lower pagename, without whitespaces or alphanumeric characters:
            pageName = child.titleShort.lower().replace(" ", "_")
            pageName = re.sub(r"\W", "", pageName)
            if not pageName:
                pageName = "__"

            self.pages.append(WebsitePage(self.prefix + pageName, depth,
                                          child))
            self.generatePages(child, depth + 1)

    def hasUncutResources(self):
        """
        Check if any of the resources in the exported package has an uncut filename
        """
        for page in self.pages:
            for idevice in page.node.idevices:
                for resource in idevice.userResources:
                    if type(resource) == Resource and len(
                            resource.storageName) > 12:
                        return True
        return False
Beispiel #60
0
    def loadSettings(self):
        """
        Loads the settings from the exe.conf file.
        Overrides the defaults set in __init__
        """

        # Set up the parser so that if a certain value is not in the config
        # file, it will use the value from our default values
        def defVal(dummy, option):
            """If something is not in the config file, just use the default in
            'self'"""
            return getattr(self, option)

        self.configParser.defaultValue = defVal
        self.upgradeFile()
        # System Section
        if self.configParser.has_section('system'):
            system = self.configParser.system

            self.port = int(system.port)
            self.browser = None if system.browser == u"None" else system.browser
            self.stylesRepository = system.stylesRepository

            if not G.application.portable:
                self.dataDir = Path(system.dataDir)
                self.configDir = Path(system.configDir)
                self.webDir = Path(system.webDir)
                self.stylesDir = Path(self.configDir) / 'style'
                self.templatesDir = Path(self.configDir) / 'content_template'
                self.jsIdevicesDir = Path(
                    self.configDir) / 'scripts' / 'idevices'
                self.jsDir = Path(system.jsDir)
            else:
                self.stylesDir = Path(self.webDir / 'style').abspath()
                self.templatesDir = Path(self.webDir /
                                         'content_template').abspath()
                self.jsIdevicesDir = Path(self.webDir / 'scripts' /
                                          'idevices').abspath()

            self.assumeMediaPlugins = False
            if self.configParser.has_option('system', 'assumeMediaPlugins'):
                value = system.assumeMediaPlugins.strip().lower()
                if value == "1" or value == "yes" or value == "true" or value == "on":
                    self.assumeMediaPlugins = True

        # If the dataDir points to some other dir, fix it
        if not self.dataDir.isdir():
            self.dataDir = tempfile.gettempdir()
        # make the webDir absolute, to hide path joins of relative paths
        self.webDir = self.webDir.expand().abspath()
        # If the configDir doesn't exist (as it may be a default setting with a
        # new installation) create it
        if not self.configDir.exists():
            self.configDir.mkdir()

        if not G.application.standalone:
            # FM: Copy styles
            if not os.path.exists(self.stylesDir) or not os.listdir(
                    self.stylesDir):
                self.copyStyles()
            else:
                self.updateStyles()

            # Copy templates
            if not os.path.exists(self.templatesDir) or not os.listdir(
                    self.templatesDir):
                self.copyTemplates()
            else:
                self.updateTemplates()

            # Copy JavaScript Idevices
            if not os.path.exists(self.jsIdevicesDir) or not os.listdir(
                    self.jsIdevicesDir):
                self.copy_js_idevices()
            else:
                self.update_js_idevices()
        else:
            if G.application.portable:
                if os.name == 'posix':
                    self.stylesDir = Path(self.webDir / '..' / '..' / '..' /
                                          'style')
                    self.templatesDir = Path(self.webDir / '..' / '..' / '..' /
                                             'content_template')
                    self.jsIdevicesDir = Path(self.webDir / '..' / '..' /
                                              '..' / 'scripts' / 'idevices')

                else:
                    self.stylesDir = Path(self.webDir / '..' / 'style')
                    self.templatesDir = Path(self.webDir / '..' /
                                             'content_template')
                    self.jsIdevicesDir = Path(self.webDir / '..' / 'scripts' /
                                              'idevices')

                if not os.path.exists(self.stylesDir) or not os.listdir(
                        self.stylesDir):
                    self.copyStyles()

                if not os.path.exists(self.templatesDir) or not os.listdir(
                        self.templatesDir):
                    self.copyTemplates()

                if not os.path.exists(self.jsIdevicesDir) or not os.listdir(
                        self.jsIdevicesDir):
                    self.copy_js_idevices()
            else:
                self.stylesDir = Path(self.webDir / 'style').abspath()
                self.templatesDir = Path(self.webDir /
                                         'content_template').abspath()
                self.jsIdevicesDir = Path(self.webDir / 'scripts' /
                                          'idevices').abspath()

        # Get the list of recently opened projects
        self.recentProjects = []
        if self.configParser.has_section('recent_projects'):
            recentProjectsSection = self.configParser.recent_projects
            # recentProjectsSection.items() is in the wrong order, keys are alright.
            # Sorting list by key before adding to self.recentProjects, to avoid wrong ordering
            # in Recent Projects menu list
            recentProjectsItems = recentProjectsSection.items()
            recentProjectsItems.sort()
            for key, path in recentProjectsItems:
                self.recentProjects.append(path)

        # Load the list of "hidden" iDevices
        self.hiddeniDevices = []
        if self.configParser.has_section('idevices'):
            idevicesSection = self.configParser.idevices
            for key, value in idevicesSection.items():
                # emulate standard library's getboolean()
                value = value.strip().lower()
                if value == "0" or value == "no" or value == "false" or \
                        value == "off":
                    self.hiddeniDevices.append(key.lower())

        # self.deprecatediDevices = [ "flash with text", "flash movie", ...]
        # and UN-Load from the list of "deprecated" iDevices
        if self.configParser.has_section('deprecated'):
            deprecatedSection = self.configParser.deprecated
            for key, value in deprecatedSection.items():
                # emulate standard library's getboolean()
                value = value.strip().lower()
                if value == "1" or value == "yes" or value == "true" or \
                        value == "on":
                    if key.lower() in self.deprecatediDevices:
                        self.deprecatediDevices.remove(key.lower())

        # Load the "user" section
        if self.configParser.has_section('user'):
            if self.configParser.user.has_option('editorMode'):
                self.editorMode = self.configParser.user.editorMode
            if self.configParser.user.has_option('editorVersion'):
                self.editorVersion = self.configParser.user.editorVersion
            if self.configParser.user.has_option('docType'):
                self.docType = self.configParser.user.docType
                common.setExportDocType(self.configParser.user.docType)
            if self.configParser.user.has_option('defaultStyle'):
                self.defaultStyle = self.configParser.user.defaultStyle
            if self.configParser.user.has_option('styleSecureMode'):
                self.styleSecureMode = self.configParser.user.styleSecureMode
            if self.configParser.user.has_option('internalAnchors'):
                self.internalAnchors = self.configParser.user.internalAnchors
            if self.configParser.user.has_option('lastDir'):
                self.lastDir = self.configParser.user.lastDir
            if self.configParser.user.has_option('showPreferencesOnStart'):
                self.showPreferencesOnStart = self.configParser.user.showPreferencesOnStart
            if self.configParser.user.has_option(
                    'showNewVersionWarningOnStart'):
                self.showNewVersionWarningOnStart = self.configParser.user.showNewVersionWarningOnStart
            if self.configParser.user.has_option('showIdevicesGrouped'):
                self.showIdevicesGrouped = self.configParser.user.showIdevicesGrouped
            if self.configParser.user.has_option('locale'):
                self.locale = self.configParser.user.locale
            if self.configParser.user.has_option('defaultLicense'):
                self.defaultLicense = self.configParser.user.defaultLicense
            if self.configParser.user.has_option('forceEditableExport'):
                self.forceEditableExport = self.configParser.user.forceEditableExport
            if self.configParser.user.has_option('cutFileName'):
                self.cutFileName = self.configParser.user.cutFileName
            if self.configParser.user.has_option('autosaveTime'):
                self.autosaveTime = self.configParser.user.autosaveTime
            if self.configParser.user.has_option('metadataWarning'):
                self.metadataWarning = self.configParser.user.metadataWarning