def import_package(self, filename, user): package = None try: zipped_file = zipfile.ZipFile(filename, "r") except zipfile.BadZipFile: log.error("File %s is not a zip file" % filename) return False temp_dir = tempfile.mkdtemp() try: for file_in_zip in zipped_file.namelist(): if file_in_zip.endswith(".json"): zipped_file.extractall(path=temp_dir) with open(Path.joinpath(Path(temp_dir), Path(file_in_zip))) as json_file: json_data = json.load(json_file) package = Package(title=json_data['title'], user=user) self._copy_resources_from_zip(json_data['files'], temp_dir, package) dublincore = DublinCore.objects.create() package.dublincore = dublincore dublincore.save() package.save() order = PackageOrder.objects.filter(user=user).aggregate(Max('sort_order'))['sort_order__max'] package_order = PackageOrder(package=package, user=user, sort_order=order) package_order.save() Node.objects.import_node(json_data['nodes'][0], package, None) finally: Path.rmtree(temp_dir) if package: return True else: return False
def set_footerImg(self, value): """Set the footer image for this package""" if self._footerImg: self._footerImg.delete() if value: if value.startswith("file://"): value = value[7:] imgFile = Path(value) self._footerImg = Resource(self, Path(imgFile)) else: self._footerImg = ''
def renderPreview(self): """ Returns an XHTML string for previewing this block """ if self.idevice.page_list: print("\n\n######################\n") print("render preview ") filename = Path.joinpath(Path(settings.MEDIA_ROOT), Path.relpath(self.idevice.pdf_file.path)) modified_filename = Path._get_namebase( filename) + "-modified-" + str( self.idevice.id) + Path._get_ext(filename) pages = pages_from_range(self.idevice.page_list) output = PdfFileWriter() input = PdfFileReader(open(filename, "rb")) for page in pages: output.addPage(input.getPage(page - 1)) with open(modified_filename, 'wb') as output_pdf: output.write(output_pdf) self.idevice.modified_pdf_file = Path(settings.MEDIA_URL).joinpath( Path(settings.MEDIA_ROOT).relpathto(Path(modified_filename))) print("\n\n######################\n") template = self.COMMON_PREVIEW if self.use_common_content else \ self.preview_template return self._render_view(template)
def save(self): """ Save a imsmanifest file and metadata to self.output_dir """ filename = "imsmanifest.xml" out = open(self.output_dir / filename, "w", encoding='utf-8') out.write(self.createXML()) out.close() # if user did not supply metadata title, description or creator # then use package title, description, or creator in imslrm # if they did not supply a package title, use the package name lrm = model_to_dict(self.package.dublincore) if lrm.get('title', '') == '': lrm['title'] = self.package.title if lrm['title'] == '': lrm['title'] = self.package.name if lrm.get('description', '') == '': lrm['description'] = self.package.description if lrm['description'] == '': lrm['description'] = self.package.title if lrm.get('creator', '') == '': lrm['creator'] = self.package.author # Metadata templateFilename = Path( settings.STATIC_ROOT) / 'templates' / 'dublincore.xml' template = open(templateFilename, 'r', encoding='utf-8').read() xml = template % lrm out = open(self.output_dir / 'dublincore.xml', 'wb') out.write(xml.encode('utf8')) out.close()
def exportWebSite2(request, client, filename, stylesDir): '''Overwrite allowed, proceed''' try: filename = Path(filename) if filename.exists(): if filename.isdir(): shutil.rmtree(filename) else: os.remove(filename) filename.makedirs() websiteExport = WebsiteExport(self.config, stylesDir, filename) websiteExport.export(package) self._startFile(client, filename) except Exception as e: log.error("EXPORT FAILED! %s" % filename) raise
def exportIpod(request, client, filename): """ Export 'client' to an iPod Notes folder tree 'webDir' is just read from config.webDir """ try: # filename is a directory where we will export the notes to # We assume that the user knows what they are doing # and don't check if the directory is already full or not # and we just overwrite what's already there filename = Path(filename) # Append the package name to the folder path if necessary if filename.basename() != package.name: filename /= package.name if not filename.exists(): filename.makedirs() elif not filename.isdir(): client.alert( _('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: client.alert( _('Folder name %s already exists. ' 'Please choose another one or delete existing one then try again.' ) % filename) return # Now do the export ipodExport = IpodExport(self.config, filename) ipodExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s') % str(e)) raise client.alert(_('Exported to %s') % filename)
def store_images(self, page): #for storing files local_path = Path.joinpath(settings.MEDIA_ROOT, settings.WIKI_CACHE_DIR) # creyoco/exedjango/exeapp_media/wiki_cache_images #for url global_path = Path.joinpath(settings.MEDIA_URL, settings.WIKI_CACHE_DIR) #create directory structure if not os.path.isdir(local_path): os.makedirs(local_path) soup = BeautifulSoup(page.html()) #save file and update link in content for img in soup.findAll('img'): image = "http:" + img['src'] filename = img['src'].split('/')[-1] filename = slugify(Path._get_namebase(filename)) + Path._get_ext(filename) #sanitizing filename file_path = Path.joinpath(local_path, Path(filename)) urllib.request.urlretrieve(image, file_path) img['src'] = Path.joinpath(global_path, Path.basename(filename)) #update image hyperlink to wiki for bigger version image for image_link in soup.findAll("a", {"class": "image"}): image_link['href'] = "http://wikipedia.org" + image_link['href'] for link in soup.findAll("a"): if link['href'].startswith("/wiki"): link['href'] = "http://wikipedia.org" + link['href'] link['target'] = "_blank" elif link['href'].startswith("//"): link['href'] = "http:" + link['href'] link['target'] = "_blank" page = soup.prettify() return page
def exportText(self, client, filename): try: filename = Path(filename) log.debug("exportWebsite, filename=%s" % filename) # Append an extension if required if not filename.lower().endswith('.txt'): filename += '.txt' if Path(filename).exists(): msg = _('"%s" already exists.\nPlease try again with a different filename') % filename client.alert(_('EXPORT FAILED!\n%s' % msg)) return # Do the export textExport = TextExport(filename) textExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s' % str(e))) raise client.alert(_('Exported to %s') % filename)
def add_dir_to_zip(self, zipped, path, rel_path=Path(".")): """ Recursively adds the dir in path + relpath and all its child dirs to zipped """ for scormFile in (path / rel_path).files(): zipped.write(scormFile, rel_path / scormFile.basename(), ZIP_DEFLATED) for directory in (path / rel_path).dirs(): self.add_dir_to_zip(zipped, path, rel_path / directory.basename())
def exportWebSite(request, client, filename, stylesDir, quick=False): """ Export 'client' to a web site, 'webDir' is just read from config.webDir 'stylesDir' is where to copy the style sheet information from """ # filename is a directory where we will export the website to filename = Path(filename) # Append the package name to the folder path if necessary if filename.basename() != package.name: filename /= package.name if filename.exists() and not quick: client.sendScript('askOverwrite("%s", "%s");' \ % (str(filename).replace("\\", "\\\\"), stylesDir.replace("\\", "\\\\"))) else: # Now do the export self.exportWebSite2(client, filename, stylesDir)
def do_zip(self): """ Actually saves the zip data. Called by 'Path.safeSave' """ tmpdir = tempfile.mkdtemp() inner_zip_file_name = self.package.zipname try: inner_zip_name = os.path.join(tmpdir, inner_zip_file_name) inner_zip = ZipFile(inner_zip_name, "w") self.add_dir_to_zip(inner_zip, Path(self.output_dir)) inner_zip.close() outer_zip = ZipFile(self.file_obj, "w") self.add_dir_to_zip(outer_zip, Path(self.output_dir)) self.add_dir_to_zip(outer_zip, Path(tmpdir)) outer_zip.close() finally: shutil.rmtree(tmpdir)
def __init__(self, *args, **kwargs): """ Initialize 'style_dir' is the directory from which we will copy our style sheets (and some gifs) """ super(IMSExport, self).__init__(*args, **kwargs) static_dir = Path(settings.STATIC_ROOT) self.templatesDir = static_dir / "templates" self.schemasDir = static_dir / "schemas/ims" self.page_class = IMSPage
def exportText(self, client, filename): try: filename = Path(filename) log.debug("exportWebsite, filename=%s" % filename) # Append an extension if required if not filename.lower().endswith('.txt'): filename += '.txt' if Path(filename).exists(): msg = _( '"%s" already exists.\nPlease try again with a different filename' ) % filename client.alert(_('EXPORT FAILED!\n%s' % msg)) return # Do the export textExport = TextExport(filename) textExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s' % str(e))) raise client.alert(_('Exported to %s') % filename)
def extractPackage(request, package, 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( _('Cannot access directory named ') + str(saveDir) + _('. Please use ASCII names.')) return # Add the extension if its not already there if not filename.lower().endswith('.elp'): filename += '.elp' if Path(filename).exists() and existOk != 'true': msg = _( '"%s" already exists.\nPlease try again with a different filename' ) % filename client.alert(_('EXTRACT FAILED!\n%s' % msg)) return try: # Create a new package for the extracted nodes newPackage = package.extractNode() # trigger a rename of all of the internal nodes and links, # and to remove any old anchors from the dest package, # and remove any zombie links via isExtract: newNode = newPackage.root if newNode: newNode.RenamedNodePath(isExtract=True) # Save the new package newPackage.save(filename) except Exception as e: client.alert(_('EXTRACT FAILED!\n%s' % str(e))) raise client.alert(_('Package extracted to: %s' % filename))
def exportScorm(request, client, filename, stylesDir, scormType): """ Exports this package to a scorm package file """ try: filename = Path(filename) log.debug("exportScorm, filename=%s" % filename) # Append an extension if required if not filename.lower().endswith('.zip'): filename += '.zip' if Path(filename).exists(): msg = _('"%s" already exists.\nPlease try again with a different filename') % filename client.alert(_('EXPORT FAILED!\n%s' % msg)) return # Do the export scormExport = ScormExport(self.config, stylesDir, filename, scormType) scormExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s' % str(e))) raise client.alert(_('Exported to %s') % filename)
def __init__(self, package, file_obj): """ 'style_dir' is the directory where we can copy the stylesheets from 'output_dir' is the directory that will be [over]written with the website """ static_dir = Path(settings.STATIC_ROOT) self.package = package self.style_dir = static_dir / "css" / "styles" / package.style self.scripts_dir = static_dir / "scripts" self.pages = [] self.json_file = self.create_temp_json_file() self.file_obj = file_obj self.media_dir = Path(package.user.profile.media_path) self.media_root = Path(os.path.abspath(settings.MEDIA_ROOT)) self.page_class = WebsitePage self.wiki_media = set() self.nonwiki_media = set() self.output_dir = Path(tempfile.mkdtemp()) print(self.output_dir)
def test_websitepage(self): IDEVICE_TYPE = "FreeTextIdevice" self.data.root.add_idevice(IDEVICE_TYPE) exporter = Mock() exporter.pages = [] exporter.style_dir = Path( settings.STATIC_ROOT) / "css" / "styles" / "bmz" websitepage = WebsitePage(self.data.root, 0, exporter) exporter.pages.append(websitepage) self.assertTrue('class="%s" id="id1"' % IDEVICE_TYPE in websitepage.render())
def from_dict(self, dic): print(dic) self.edit = dic['edit'] soup = BeautifulSoup(dic['content']) images = soup.findAll("img") for img in images: img['src'] = Path.joinpath(self.parent_node.package.user.profile.media_url, img['src']) self.content = soup.prettify() self.date_created = datetime.now() self.save() FreeTextVersion.objects.create(idevice=self, content=self.content, date_created=self.date_created) return self
def exportWebZip(request, client, filename, stylesDir): try: log.debug("exportWebsite, filename=%s" % filename) filename = Path(filename) # Do the export filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) websiteExport = WebsiteExport(self.config, stylesDir, filename) websiteExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s' % str(e))) raise client.alert(_('Exported to %s') % filename)
def exportIpod(request, client, filename): """ Export 'client' to an iPod Notes folder tree 'webDir' is just read from config.webDir """ try: # filename is a directory where we will export the notes to # We assume that the user knows what they are doing # and don't check if the directory is already full or not # and we just overwrite what's already there filename = Path(filename) # Append the package name to the folder path if necessary if filename.basename() != package.name: filename /= package.name if not filename.exists(): filename.makedirs() elif not filename.isdir(): client.alert(_('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: client.alert(_('Folder name %s already exists. ' 'Please choose another one or delete existing one then try again.') % filename) return # Now do the export ipodExport = IpodExport(self.config, filename) ipodExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s') % str(e)) raise client.alert(_('Exported to %s') % filename)
def import_package(self, filename, user): package = None try: zipped_file = zipfile.ZipFile(filename, "r") except zipfile.BadZipFile: log.error("File %s is not a zip file" % filename) return False temp_dir = tempfile.mkdtemp() try: for file_in_zip in zipped_file.namelist(): if file_in_zip.endswith(".json"): zipped_file.extractall(path=temp_dir) with open(Path.joinpath(Path(temp_dir), Path(file_in_zip))) as json_file: json_data = json.load(json_file) package = Package(title=json_data['title'], user=user) self._copy_resources_from_zip(json_data['files'], temp_dir, package) dublincore = DublinCore.objects.create() package.dublincore = dublincore dublincore.save() package.save() order = PackageOrder.objects.filter( user=user).aggregate( Max('sort_order'))['sort_order__max'] package_order = PackageOrder(package=package, user=user, sort_order=order) package_order.save() Node.objects.import_node(json_data['nodes'][0], package, None) finally: Path.rmtree(temp_dir) if package: return True else: return False
def exportSinglePage(request, client, filename, webDir, stylesDir, \ printFlag): """ Export 'client' to a single web page, 'webDir' is just read from config.webDir 'stylesDir' is where to copy the style sheet information from 'printFlag' indicates whether or not this is for print (and whatever else that might mean) """ try: imagesDir = webDir.joinpath('images') scriptsDir = webDir.joinpath('scripts') templatesDir = webDir.joinpath('templates') # filename is a directory where we will export the website to # We assume that the user knows what they are doing # and don't check if the directory is already full or not # and we just overwrite what's already there filename = Path(filename) # Append the package name to the folder path if necessary if filename.basename() != package.name: filename /= package.name if not filename.exists(): filename.makedirs() elif not filename.isdir(): client.alert( _('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: client.alert( _('Folder name %s already exists. ' 'Please choose another one or delete existing one then try again.' ) % filename) return # Now do the export singlePageExport = SinglePageExport(stylesDir, filename, \ imagesDir, scriptsDir, templatesDir) singlePageExport.export(package, printFlag) except Exception as e: client.alert(_('SAVE FAILED!\n%s' % str(e))) raise # Show the newly exported web site in a new window if not printFlag: self._startFile(client, filename) # and return a string of the actual directory name, # in case the package name was added, etc.: return filename.abspath().encode('utf-8')
def extractPackage(request, package, 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(_('Cannot access directory named ') + str(saveDir) + _('. Please use ASCII names.')) return # Add the extension if its not already there if not filename.lower().endswith('.elp'): filename += '.elp' if Path(filename).exists() and existOk != 'true': msg = _('"%s" already exists.\nPlease try again with a different filename') % filename client.alert(_('EXTRACT FAILED!\n%s' % msg)) return try: # Create a new package for the extracted nodes newPackage = package.extractNode() # trigger a rename of all of the internal nodes and links, # and to remove any old anchors from the dest package, # and remove any zombie links via isExtract: newNode = newPackage.root if newNode: newNode.RenamedNodePath(isExtract=True) # Save the new package newPackage.save(filename) except Exception as e: client.alert(_('EXTRACT FAILED!\n%s' % str(e))) raise client.alert(_('Package extracted to: %s' % filename))
def exportScorm(request, client, filename, stylesDir, scormType): """ Exports this package to a scorm package file """ try: filename = Path(filename) log.debug("exportScorm, filename=%s" % filename) # Append an extension if required if not filename.lower().endswith('.zip'): filename += '.zip' if Path(filename).exists(): msg = _( '"%s" already exists.\nPlease try again with a different filename' ) % filename client.alert(_('EXPORT FAILED!\n%s' % msg)) return # Do the export scormExport = ScormExport(self.config, stylesDir, filename, scormType) scormExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s' % str(e))) raise client.alert(_('Exported to %s') % filename)
def from_dict(self, dic): print(dic) self.edit = dic['edit'] soup = BeautifulSoup(dic['content']) images = soup.findAll("img") for img in images: img['src'] = Path.joinpath( self.parent_node.package.user.profile.media_url, img['src']) self.content = soup.prettify() self.date_created = datetime.now() self.save() FreeTextVersion.objects.create(idevice=self, content=self.content, date_created=self.date_created) return self
def to_dict(self): d = self.__dict__ d = { k: v for k, v in d.items() if k != 'id' and k != 'idevice_ptr_id' and k != 'parent_node_id' and k != 'date_created' and not k.startswith('_') } d['child_type'] = self.get_klass() soup = BeautifulSoup(d['content']) images = soup.findAll("img") for img in images: img['src'] = Path(img['src']).basename() d['content'] = soup.prettify() return d
def renderPreview(self): """ Returns an XHTML string for previewing this block """ if self.idevice.page_list: print("\n\n######################\n") print("render preview ") filename = Path.joinpath(Path(settings.MEDIA_ROOT),Path.relpath(self.idevice.pdf_file.path)) modified_filename = Path._get_namebase(filename) + "-modified-"+ str(self.idevice.id)+ Path._get_ext(filename) pages = pages_from_range(self.idevice.page_list) output = PdfFileWriter() input = PdfFileReader(open(filename, "rb")) for page in pages: output.addPage(input.getPage(page-1)) with open(modified_filename,'wb') as output_pdf: output.write(output_pdf) self.idevice.modified_pdf_file = Path(settings.MEDIA_URL).joinpath(Path(settings.MEDIA_ROOT).relpathto(Path(modified_filename))) print("\n\n######################\n") template = self.COMMON_PREVIEW if self.use_common_content else \ self.preview_template return self._render_view(template)
def copy_resources(self): view_media = set() for page in self.pages: view_media = view_media.union(page.view_media._js). \ union(page.view_media._css.get('all', [])) view_media = [ unquote(medium.replace(settings.STATIC_URL, "")) for medium in view_media if not "tinymce" in medium ] Path(settings.STATIC_ROOT).copylist(view_media, self.output_dir) for x in self.package.resources: if settings.WIKI_CACHE_DIR in x: self.wiki_media.add(x) else: self.nonwiki_media.add(x) self.media_dir.copylist(self.nonwiki_media, self.output_dir) self.media_root.copylist(self.wiki_media, self.output_dir)
def exportSinglePage(request, client, filename, webDir, stylesDir, \ printFlag): """ Export 'client' to a single web page, 'webDir' is just read from config.webDir 'stylesDir' is where to copy the style sheet information from 'printFlag' indicates whether or not this is for print (and whatever else that might mean) """ try: imagesDir = webDir.joinpath('images') scriptsDir = webDir.joinpath('scripts') templatesDir = webDir.joinpath('templates') # filename is a directory where we will export the website to # We assume that the user knows what they are doing # and don't check if the directory is already full or not # and we just overwrite what's already there filename = Path(filename) # Append the package name to the folder path if necessary if filename.basename() != package.name: filename /= package.name if not filename.exists(): filename.makedirs() elif not filename.isdir(): client.alert(_('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: client.alert(_('Folder name %s already exists. ' 'Please choose another one or delete existing one then try again.') % filename) return # Now do the export singlePageExport = SinglePageExport(stylesDir, filename, \ imagesDir, scriptsDir, templatesDir) singlePageExport.export(package, printFlag) except Exception as e: client.alert(_('SAVE FAILED!\n%s' % str(e))) raise # Show the newly exported web site in a new window if not printFlag: self._startFile(client, filename) # and return a string of the actual directory name, # in case the package name was added, etc.: return filename.abspath().encode('utf-8')
def loadCC(zippedFile, filename): """ Load an IMS Common Cartridge or Content Package from filename """ package = Package(Path(filename).namebase) xmldoc = minidom.parseString(zippedFile.read('imsmanifest.xml')) organizations_list = xmldoc.getElementsByTagName('organizations') level = 0 # now a two-pass system to first unzip all applicable resources: for pass_num in range(2): for organizations in organizations_list: organization_list = organizations.getElementsByTagName( 'organization') for organization in organization_list: for item in organization.childNodes: if item.nodeName == 'item': loadNode(pass_num, package.resourceDir, zippedFile, package.root, xmldoc, item, level) return package
def __init__(self, *args, **kwargs): """ Initialize 'styleDir' is the directory from which we will copy our style sheets (and some gifs) """ if "scorm_type" in kwargs: self.scorm_type = kwargs['scorm_type'] del kwargs["scorm_type"] else: raise TypeError("ScormExport requires a kw argument scorm_type") super(ScormExport, self).__init__(*args, **kwargs) static_dir = Path(settings.STATIC_ROOT) self.imagesDir = static_dir / "images" self.templatesDir = static_dir / "templates" self.schemasDir = static_dir / "schemas" self.hasForum = False self.page_class = ScormPage
def updateRecentDocuments(self, filename): """ Updates the list of recent documents """ # TODO Fix the function return 0 # Don't update the list for the generic.data "package" genericData = G.application.config.configDir / 'idevices' / \ 'generic.data' if genericData.isfile() or genericData.islink(): if Path(filename).samefile(genericData): return # Save in recentDocuments list recentProjects = G.application.config.recentProjects if filename in recentProjects: # If we're already number one, carry on if recentProjects[0] == filename: return recentProjects.remove(filename) recentProjects.insert(0, filename) del recentProjects[5:] # Delete any older names from the list G.application.config.configParser.write() # Save the settings
def createMetaData(self): """ if user did not supply metadata title, description or creator then use package title, description, or creator in imslrm if they did not supply a package title, use the package name if they did not supply a date, use today """ if self.scorm_type == SCORM12: template_name = 'imslrm.xml' elif self.scorm_type == COMMONCARTRIDGE: template_name = 'cc.xml' else: raise AttributeError("Can't create metadata for %s" \ % self.scorm_type) static_dir = Path(settings.STATIC_ROOT) templateFilename = static_dir / 'templates' / template_name template = open(templateFilename, 'r', encoding='utf-8').read() lrm = model_to_dict(self.package.dublincore) if lrm.get('title', '') == '': lrm['title'] = self.package.title if lrm['title'] == '': lrm['title'] = self.package.name if lrm.get('description', '') == '': lrm['description'] = self.package.description if lrm['description'] == '': lrm['description'] = self.package.title if lrm.get('creator', '') == '': lrm['creator'] = self.package.author if lrm['date'] == '': lrm['date'] = time.strftime('%Y-%m-%d') # if they don't look like VCARD entries, coerce to fn: for f in ('creator', 'publisher', 'contributors'): if re.match('.*[:;]', lrm[f]) == None: lrm[f] = 'FN:' + lrm[f] xml = template % lrm return xml
def exportPresentation(request, client, filename, stylesDir): """ export client to a DOM presentation """ try: # filename is a directory where we will export the website to # We assume that the user knows what they are doing # and don't check if the directory is already full or not # and we just overwrite what's already there filename = Path(filename) # Append the package name to the folder path if necessary if filename.basename() != package.name: filename /= package.name if not filename.exists(): filename.makedirs() elif not filename.isdir(): client.alert( _('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: client.alert( _('Folder name %s already exists. ' 'Please choose another one or delete existing one then try again.' ) % filename) return # Now do the export presentationExport = PresentationExport(self.config, stylesDir, filename) presentationExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s') % str(e)) raise # show new presentation in a new window self._startFile(client, filename)
def exportPresentation(request, client, filename, stylesDir): """ export client to a DOM presentation """ try: # filename is a directory where we will export the website to # We assume that the user knows what they are doing # and don't check if the directory is already full or not # and we just overwrite what's already there filename = Path(filename) # Append the package name to the folder path if necessary if filename.basename() != package.name: filename /= package.name if not filename.exists(): filename.makedirs() elif not filename.isdir(): client.alert(_('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: client.alert(_('Folder name %s already exists. ' 'Please choose another one or delete existing one then try again.') % filename) return # Now do the export presentationExport = PresentationExport(self.config, stylesDir, filename) presentationExport.export(package) except Exception as e: client.alert(_('EXPORT FAILED!\n%s') % str(e)) raise # show new presentation in a new window self._startFile(client, filename)
class WebsiteExport(object): """ WebsiteExport will export a package as a website of HTML pages """ title = "Website (Zip)" def __init__(self, package, file_obj): """ 'style_dir' is the directory where we can copy the stylesheets from 'output_dir' is the directory that will be [over]written with the website """ static_dir = Path(settings.STATIC_ROOT) self.package = package self.style_dir = static_dir / "css" / "styles" / package.style self.scripts_dir = static_dir / "scripts" self.pages = [] self.json_file = self.create_temp_json_file() self.file_obj = file_obj self.media_dir = Path(package.user.profile.media_path) self.media_root = Path(os.path.abspath(settings.MEDIA_ROOT)) self.page_class = WebsitePage self.wiki_media = set() self.nonwiki_media = set() self.output_dir = Path(tempfile.mkdtemp()) print(self.output_dir) def export(self): """ Export web site Cleans up the previous packages pages and performs the export """ self.create_pages() self.save_pages() self.copy_files() # Zip up the website package self.do_zip() # Clean up the temporary dir self.output_dir.rmtree() def do_zip(self): """ Actually saves the zip data. Called by 'Path.safeSave' """ tmpdir = tempfile.mkdtemp() inner_zip_file_name = self.package.zipname try: inner_zip_name = os.path.join(tmpdir, inner_zip_file_name) inner_zip = ZipFile(inner_zip_name, "w") self.add_dir_to_zip(inner_zip, Path(self.output_dir)) inner_zip.close() outer_zip = ZipFile(self.file_obj, "w") self.add_dir_to_zip(outer_zip, Path(self.output_dir)) self.add_dir_to_zip(outer_zip, Path(tmpdir)) outer_zip.close() finally: shutil.rmtree(tmpdir) def add_dir_to_zip(self, zipped, path, rel_path=Path(".")): """ Recursively adds the dir in path + relpath and all its child dirs to zipped """ for scormFile in (path / rel_path).files(): zipped.write(scormFile, rel_path / scormFile.basename(), ZIP_DEFLATED) for directory in (path / rel_path).dirs(): self.add_dir_to_zip(zipped, path, rel_path / directory.basename()) def copy_style_files(self): """Copy style fiels to the export package""" style_files = ["%s/../base.css" % self.style_dir, "%s/../popup_bg.gif" % self.style_dir] style_files += self.style_dir.files("*.css") style_files += self.style_dir.files("*.jpg") style_files += self.style_dir.files("*.gif") style_files += self.style_dir.files("*.svg") style_files += self.style_dir.files("*.png") style_files += self.style_dir.files("*.js") style_files += self.style_dir.files("*.html") self.style_dir.copylist(style_files, self.output_dir) if (self.style_dir / "img").exists(): (self.style_dir / "img").copytree(self.output_dir / "img") if (self.style_dir / "js").exists(): (self.style_dir / "js").copytree(self.output_dir / "js") if (self.style_dir / "fonts").exists(): (self.style_dir / "fonts").copytree(self.output_dir / "fonts") def copy_licence(self): """Copy licence file""" if self.package.license == "GNU Free Documentation License": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile( self.output_dir / 'fdl.html') def copy_files(self): """ Copy all the files used by the website. """ # Copy the style sheet files to the output dir self.copy_style_files() self.copy_resources() self.scripts_dir.copylist(('libot_drag.js', 'bower_components/jquery/jquery.js'), self.output_dir) self.copy_players() self.copy_licence() self.copy_json() def create_pages(self, additional_kwargs=None): additional_kwargs = additional_kwargs or {} self.pages.append(self.page_class(self.package.root, 1, exporter=self, **additional_kwargs)) self.generate_pages(self.package.root, 1, additional_kwargs) def save_pages(self): for page in self.pages: page.save(self.output_dir) def copy_players(self): has_flowplayer = False has_magnifier = False has_xspfplayer = False is_break = False for page in self.pages: if is_break: break for idevice in page.node.idevices.all(): resources = idevice.as_child().system_resources if has_flowplayer and has_magnifier and has_xspfplayer: is_break = True break if not has_flowplayer: if 'flowPlayer.swf' in resources: has_flowplayer = True if not has_magnifier: if 'magnifier.swf' in resources: has_magnifier = True if not has_xspfplayer: if 'xspf_player.swf' in resources: has_xspfplayer = True def copy_resources(self): view_media = set() for page in self.pages: view_media = view_media.union(page.view_media._js). \ union(page.view_media._css.get('all', [])) view_media = [unquote(medium.replace(settings.STATIC_URL, "")) for medium in view_media if not "tinymce" in medium] Path(settings.STATIC_ROOT).copylist(view_media, self.output_dir) for x in self.package.resources: if settings.WIKI_CACHE_DIR in x: self.wiki_media.add(x) else: self.nonwiki_media.add(x) self.media_dir.copylist(self.nonwiki_media, self.output_dir) self.media_root.copylist(self.wiki_media, self.output_dir) def generate_pages(self, node, depth, kwargs=None): """ Recursively generate pages and store in pages member variable for retrieving later. Kwargs will be used at page creation. """ kwargs = kwargs or {} for child in node.children.all(): page = self.page_class(child, depth, exporter=self, has_children=child.children.exists(), **kwargs) last_page = self.pages[-1] if self.pages else None if last_page: page.prev_page = last_page last_page.next_page = page self.pages.append(page) self.generate_pages(child, depth + 1) def _cleanup_dict(self, dic): return dict([(x, y) for x, y in dic.items() if not x.startswith('_')]) def dict_of_node(self, node): print(node.id) node_dict = self._cleanup_dict(node.__dict__) child_list = [] if node.children.count(): i = 0 for child in node.children.all(): i = i + 1 print(i) child_list.append(self.dict_of_node(child)) node_dict['children'] = child_list node_dict['idevices'] = [] for idevice in node.idevices.all(): child = idevice.as_child() # add todict for every idevice clean_dict = child.to_dict() node_dict['idevices'].append(clean_dict) return node_dict def create_json(self): print("json") dict_for_json = self._cleanup_dict(self.package.to_dict()) dict_for_json['files'] = [] for f in self.wiki_media: dict_for_json['files'].append(f) for f in self.nonwiki_media: dict_for_json['files'].append(f) for node in self.package.nodes.all(): dict_for_json['nodes'] = [] dict_for_json['nodes'].append(self.dict_of_node(node)) with open(self.json_file, "w") as out: out.write(json.dumps(dict_for_json)) def copy_json(self): self.create_json() Path.copyfile(self.json_file, Path.joinpath(self.output_dir, Path("a.json"))) def create_temp_json_file(self): f = tempfile.NamedTemporaryFile(mode='w+t', suffix='.json', prefix='', delete=False) _filename = f.name f.close() return _filename
def previewTinyMCEimage(request, package, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, local_filename, preview_filename): """ Once an image is selected in the file browser that is spawned by the TinyMCE image dialog, copy this file (which is local to the user's machine) into the server space, under a preview directory (after checking if this exists, and creating it if necessary). Note that this IS a "cheat", in violation of the client-server separation, but can be done since we know that the eXe server is actually sitting on the client host. """ server_filename = "" callback_errors = "" errors = 0 log.debug('handleTinyMCEimageChoice: image local = ' + local_filename + ', base=' + os.path.basename(local_filename)) webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert(\ _('Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: " + "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 if errors == 0: log.debug('handleTinyMCEimageChoice: originally, local_filename=' + local_filename) local_filename = str(local_filename, 'utf-8') log.debug('handleTinyMCEimageChoice: in unicode, local_filename=' + local_filename) localImagePath = Path(local_filename) log.debug('handleTinyMCEimageChoice: after Path, localImagePath= ' + localImagePath) if not localImagePath.exists() or not localImagePath.isfile(): client.alert(\ _('Local file %s is not found, cannot preview it') \ % localImagePath) log.error("Couldn't find tinyMCE-chosen image: %s" \ % localImagePath) callback_errors = "Image file %s not found, cannot preview" \ % localImagePath errors += 1 try: # joinpath needs its join arguments to already be in Unicode: # preview_filename = toUnicode(preview_filename); # but that's okay, cuz preview_filename is now URI safe, right? log.debug('URIencoded preview filename=' + preview_filename) server_filename = previewDir.joinpath(preview_filename) log.debug("handleTinyMCEimageChoice copying image from \'"\ + local_filename + "\' to \'" \ + server_filename.abspath() + "\'.") shutil.copyfile(local_filename, \ server_filename.abspath()) # new optional description file to provide the # actual base filename, such that once it is later processed # copied into the resources directory, it can be done with # only the basename. Otherwise the resource filenames # are too long for some users, preventing them from making # backup CDs of the content, for example. # # Remember that the full path of the # file is only used here as an easy way to keep the names # unique WITHOUT requiring a roundtrip call from the Javascript # to this server, and back again, a process which does not # seem to work with tinyMCE in the mix. BUT, once tinyMCE's # part is done, and this image processed, it can be returned # to just its basename, since the resource parts have their # own unique-ification mechanisms already in place. descrip_file_path = Path(server_filename + ".exe_info") log.debug("handleTinyMCEimageChoice creating preview " \ + "description file \'" \ + descrip_file_path.abspath() + "\'.") descrip_file = open(descrip_file_path, 'wb') # safety measures against TinyMCE, otherwise it will # later take ampersands and entity-escape them into '&', # and filenames with hash signs will not be found, etc.: unspaced_filename = local_filename.replace(' ', '_') unhashed_filename = unspaced_filename.replace('#', '_num_') unamped_local_filename = unhashed_filename.replace('&', '_and_') log.debug("and setting new file basename as: " + unamped_local_filename) my_basename = os.path.basename(unamped_local_filename) descrip_file.write(("basename=" + my_basename).encode('utf-8')) descrip_file.flush() descrip_file.close() except Exception as e: client.alert(_('SAVE FAILED!\n%s' % str(e))) log.error("handleTinyMCEimageChoice unable to copy local image "\ + "file to server prevew, error = " + str(e)) raise
def generateTinyMCEmath(request, package, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, latex_source, math_fontsize, \ preview_image_filename, preview_math_srcfile): """ Based off of handleTinyMCEimageChoice(), handleTinyMCEmath() is similar in that it places a .gif math image (and a corresponding .tex LaTeX source file) into the previews dir. Rather than copying the image from a user-selected directory, though, this routine actually generates the math image using mimetex. """ server_filename = "" callback_errors = "" errors = 0 webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert(\ _('Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: " + "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 # if errors == 0: # localImagePath = Path(local_filename) # if not localImagePath.exists() or not localImagePath.isfile(): # client.alert( \ # _(u'Image file %s is not found, cannot preview it') \ # % localImagePath) # log.error("Couldn't find tinyMCE-chosen image: %s" \ # % localImagePath) # callback_errors = "Image file %s not found, cannot preview" \ # % localImagePath # errors += 1 # the mimetex usage code was swiped from the Math iDevice: if latex_source != "": # first write the latex_source out into the preview_math_srcfile, # such that it can then be passed into the compile command: math_filename = previewDir.joinpath(preview_math_srcfile) math_filename_str = math_filename.abspath().encode('utf-8') log.info("handleTinyMCEmath: using LaTeX source: " + latex_source) log.debug("writing LaTeX source into \'" \ + math_filename_str + "\'.") math_file = open(math_filename, 'wb') # do we need to append a \n here?: math_file.write(latex_source) math_file.flush() math_file.close() try: use_latex_sourcefile = math_filename_str tempFileName = compile(use_latex_sourcefile, math_fontsize, \ latex_is_file=True) except Exception as e: client.alert(_('MimeTeX compile failed!\n%s' % str(e))) log.error("handleTinyMCEmath unable to compile LaTeX using "\ + "mimetex, error = " + str(e)) raise # copy the file into previews server_filename = previewDir.joinpath(preview_image_filename) log.debug("handleTinyMCEmath copying math image from \'"\ + tempFileName + "\' to \'" \ + server_filename.abspath().encode('utf-8') + "\'.") shutil.copyfile(tempFileName, \ server_filename.abspath().encode('utf-8')) # Delete the temp file made by compile Path(tempFileName).remove() return
def exportPackage(request, package, exportType, filename, print_callback='', quick=False): """ Called by js. Exports the current package to one of the above formats 'exportType' can be one of 'singlePage' 'webSite' 'zipFile' 'ipod' 'textFile' 'scorm' or 'presentation' 'filename' is a file for scorm pages, and a directory for websites """ G.application.lastExportType = exportType G.application.lastExportPath = filename client.sendScript('document.getElementById("quick-export")' + \ '.setAttribute("disabled", "false");') client.sendScript('document.getElementById("serving-elem")' + \ '.setAttribute("disabled", "false");') client.sendScript('document.getElementById("serving-elem")' + \ '.setAttribute("label", "Start Serving");') client.sendScript('document.getElementById("serving-elem")' + \ '.setAttribute("oncommand", "serveDocument\(\)");') client.sendScript('document.getElementById("quick-export").' + \ 'setAttribute("disabled", "false");') log.info("Filename to export" + filename) webDir = Path(self.config.webDir) if package.style.find("locale/") != -1: # local style loaded stylesDir = self.config.configDir / "style" # delete "locale/" from style name stylesDir /= package.style[package.style.find\ ("locale/") + len("locale/"):] else: # global style stylesDir = webDir / "style" stylesDir /= package.style exportDir = Path(filename).dirname() if exportDir and not exportDir.exists(): client.alert(_('Cannot access directory named ') + str(exportDir) + _('. Please use ASCII names.')) return """ adding the print feature in using the same export functionality: """ if exportType == 'singlePage' or exportType == 'printSinglePage': printit = 0 if exportType == 'printSinglePage': printit = 1 exported_dir = self.exportSinglePage(client, filename, webDir, \ stylesDir, printit) # the above will return None if the desired exported directory # already exists (printing always goes to a new temp dir, though): if printit == 1 and not exported_dir is None: web_printdir = self.get_printdir_relative2web(exported_dir) # now that this has ben exported, go ahead and trigger # the requested printing callback: client.call(print_callback, filename, exported_dir, \ web_printdir) elif exportType == 'webSite': self.exportWebSite(client, filename, stylesDir, quick=quick) elif exportType == 'presentation': self.exportPresentation(client, filename, stylesDir) elif exportType == 'printHandout': exported_dir = self.printHandout(client, filename, stylesDir) print(exported_dir) web_printdir = self.get_printdir_relative2web(exported_dir) client.call(print_callback, filename, exported_dir, web_printdir) elif exportType == 'zipFile': filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportWebZip(client, filename, stylesDir) elif exportType == 'textFile': self.exportText(client, filename) elif exportType == 'ipod': self.exportIpod(client, filename) elif exportType == "scorm": filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm1.2") elif exportType == "scorm2004": filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm2004") elif exportType == "commoncartridge": filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "commoncartridge") else: filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportIMS(client, filename, stylesDir)
def generateTinyMCEmath(request, package, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, latex_source, math_fontsize, \ preview_image_filename, preview_math_srcfile): """ Based off of handleTinyMCEimageChoice(), handleTinyMCEmath() is similar in that it places a .gif math image (and a corresponding .tex LaTeX source file) into the previews dir. Rather than copying the image from a user-selected directory, though, this routine actually generates the math image using mimetex. """ server_filename = "" callback_errors = "" errors = 0 webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert(\ _('Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: " + "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 # if errors == 0: # localImagePath = Path(local_filename) # if not localImagePath.exists() or not localImagePath.isfile(): # client.alert( \ # _(u'Image file %s is not found, cannot preview it') \ # % localImagePath) # log.error("Couldn't find tinyMCE-chosen image: %s" \ # % localImagePath) # callback_errors = "Image file %s not found, cannot preview" \ # % localImagePath # errors += 1 # the mimetex usage code was swiped from the Math iDevice: if latex_source != "": # first write the latex_source out into the preview_math_srcfile, # such that it can then be passed into the compile command: math_filename = previewDir.joinpath(preview_math_srcfile) math_filename_str = math_filename.abspath().encode('utf-8') log.info("handleTinyMCEmath: using LaTeX source: " + latex_source) log.debug("writing LaTeX source into \'" \ + math_filename_str + "\'.") math_file = open(math_filename, 'wb') # do we need to append a \n here?: math_file.write(latex_source) math_file.flush() math_file.close() try: use_latex_sourcefile = math_filename_str tempFileName = compile(use_latex_sourcefile, math_fontsize, \ latex_is_file=True) except Exception as e: client.alert(_('MimeTeX compile failed!\n%s' % str(e))) log.error("handleTinyMCEmath unable to compile LaTeX using "\ + "mimetex, error = " + str(e)) raise # copy the file into previews server_filename = previewDir.joinpath(preview_image_filename); log.debug("handleTinyMCEmath copying math image from \'"\ + tempFileName + "\' to \'" \ + server_filename.abspath().encode('utf-8') + "\'."); shutil.copyfile(tempFileName, \ server_filename.abspath().encode('utf-8')); # Delete the temp file made by compile Path(tempFileName).remove() return
def previewTinyMCEimage(request, package, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, local_filename, preview_filename): """ Once an image is selected in the file browser that is spawned by the TinyMCE image dialog, copy this file (which is local to the user's machine) into the server space, under a preview directory (after checking if this exists, and creating it if necessary). Note that this IS a "cheat", in violation of the client-server separation, but can be done since we know that the eXe server is actually sitting on the client host. """ server_filename = "" callback_errors = "" errors = 0 log.debug('handleTinyMCEimageChoice: image local = ' + local_filename + ', base=' + os.path.basename(local_filename)) webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert(\ _('Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: " + "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 if errors == 0: log.debug('handleTinyMCEimageChoice: originally, local_filename=' + local_filename) local_filename = str(local_filename, 'utf-8') log.debug('handleTinyMCEimageChoice: in unicode, local_filename=' + local_filename) localImagePath = Path(local_filename) log.debug('handleTinyMCEimageChoice: after Path, localImagePath= ' + localImagePath); if not localImagePath.exists() or not localImagePath.isfile(): client.alert(\ _('Local file %s is not found, cannot preview it') \ % localImagePath) log.error("Couldn't find tinyMCE-chosen image: %s" \ % localImagePath) callback_errors = "Image file %s not found, cannot preview" \ % localImagePath errors += 1 try: # joinpath needs its join arguments to already be in Unicode: # preview_filename = toUnicode(preview_filename); # but that's okay, cuz preview_filename is now URI safe, right? log.debug('URIencoded preview filename=' + preview_filename); server_filename = previewDir.joinpath(preview_filename); log.debug("handleTinyMCEimageChoice copying image from \'"\ + local_filename + "\' to \'" \ + server_filename.abspath() + "\'."); shutil.copyfile(local_filename, \ server_filename.abspath()); # new optional description file to provide the # actual base filename, such that once it is later processed # copied into the resources directory, it can be done with # only the basename. Otherwise the resource filenames # are too long for some users, preventing them from making # backup CDs of the content, for example. # # Remember that the full path of the # file is only used here as an easy way to keep the names # unique WITHOUT requiring a roundtrip call from the Javascript # to this server, and back again, a process which does not # seem to work with tinyMCE in the mix. BUT, once tinyMCE's # part is done, and this image processed, it can be returned # to just its basename, since the resource parts have their # own unique-ification mechanisms already in place. descrip_file_path = Path(server_filename + ".exe_info") log.debug("handleTinyMCEimageChoice creating preview " \ + "description file \'" \ + descrip_file_path.abspath() + "\'."); descrip_file = open(descrip_file_path, 'wb') # safety measures against TinyMCE, otherwise it will # later take ampersands and entity-escape them into '&', # and filenames with hash signs will not be found, etc.: unspaced_filename = local_filename.replace(' ', '_') unhashed_filename = unspaced_filename.replace('#', '_num_') unamped_local_filename = unhashed_filename.replace('&', '_and_') log.debug("and setting new file basename as: " + unamped_local_filename); my_basename = os.path.basename(unamped_local_filename) descrip_file.write(("basename=" + my_basename).encode('utf-8')) descrip_file.flush() descrip_file.close() except Exception as e: client.alert(_('SAVE FAILED!\n%s' % str(e))) log.error("handleTinyMCEimageChoice unable to copy local image "\ + "file to server prevew, error = " + str(e)) raise
def exportPackage(request, package, exportType, filename, print_callback='', quick=False): """ Called by js. Exports the current package to one of the above formats 'exportType' can be one of 'singlePage' 'webSite' 'zipFile' 'ipod' 'textFile' 'scorm' or 'presentation' 'filename' is a file for scorm pages, and a directory for websites """ G.application.lastExportType = exportType G.application.lastExportPath = filename client.sendScript('document.getElementById("quick-export")' + \ '.setAttribute("disabled", "false");') client.sendScript('document.getElementById("serving-elem")' + \ '.setAttribute("disabled", "false");') client.sendScript('document.getElementById("serving-elem")' + \ '.setAttribute("label", "Start Serving");') client.sendScript('document.getElementById("serving-elem")' + \ '.setAttribute("oncommand", "serveDocument\(\)");') client.sendScript('document.getElementById("quick-export").' + \ 'setAttribute("disabled", "false");') log.info("Filename to export" + filename) webDir = Path(self.config.webDir) if package.style.find("locale/") != -1: # local style loaded stylesDir = self.config.configDir / "style" # delete "locale/" from style name stylesDir /= package.style[package.style.find\ ("locale/") + len("locale/"):] else: # global style stylesDir = webDir / "style" stylesDir /= package.style exportDir = Path(filename).dirname() if exportDir and not exportDir.exists(): client.alert( _('Cannot access directory named ') + str(exportDir) + _('. Please use ASCII names.')) return """ adding the print feature in using the same export functionality: """ if exportType == 'singlePage' or exportType == 'printSinglePage': printit = 0 if exportType == 'printSinglePage': printit = 1 exported_dir = self.exportSinglePage(client, filename, webDir, \ stylesDir, printit) # the above will return None if the desired exported directory # already exists (printing always goes to a new temp dir, though): if printit == 1 and not exported_dir is None: web_printdir = self.get_printdir_relative2web(exported_dir) # now that this has ben exported, go ahead and trigger # the requested printing callback: client.call(print_callback, filename, exported_dir, \ web_printdir) elif exportType == 'webSite': self.exportWebSite(client, filename, stylesDir, quick=quick) elif exportType == 'presentation': self.exportPresentation(client, filename, stylesDir) elif exportType == 'printHandout': exported_dir = self.printHandout(client, filename, stylesDir) print(exported_dir) web_printdir = self.get_printdir_relative2web(exported_dir) client.call(print_callback, filename, exported_dir, web_printdir) elif exportType == 'zipFile': filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportWebZip(client, filename, stylesDir) elif exportType == 'textFile': self.exportText(client, filename) elif exportType == 'ipod': self.exportIpod(client, filename) elif exportType == "scorm": filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm1.2") elif exportType == "scorm2004": filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm2004") elif exportType == "commoncartridge": filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "commoncartridge") else: filename = self.b4save(client, filename, '.zip', _('EXPORT FAILED!')) self.exportIMS(client, filename, stylesDir)
def copy_json(self): self.create_json() Path.copyfile(self.json_file, Path.joinpath(self.output_dir, Path("a.json")))
class WebsiteExport(object): """ WebsiteExport will export a package as a website of HTML pages """ title = "Website (Zip)" def __init__(self, package, file_obj): """ 'style_dir' is the directory where we can copy the stylesheets from 'output_dir' is the directory that will be [over]written with the website """ static_dir = Path(settings.STATIC_ROOT) self.package = package self.style_dir = static_dir / "css" / "styles" / package.style self.scripts_dir = static_dir / "scripts" self.pages = [] self.json_file = self.create_temp_json_file() self.file_obj = file_obj self.media_dir = Path(package.user.profile.media_path) self.media_root = Path(os.path.abspath(settings.MEDIA_ROOT)) self.page_class = WebsitePage self.wiki_media = set() self.nonwiki_media = set() self.output_dir = Path(tempfile.mkdtemp()) print(self.output_dir) def export(self): """ Export web site Cleans up the previous packages pages and performs the export """ self.create_pages() self.save_pages() self.copy_files() # Zip up the website package self.do_zip() # Clean up the temporary dir self.output_dir.rmtree() def do_zip(self): """ Actually saves the zip data. Called by 'Path.safeSave' """ tmpdir = tempfile.mkdtemp() inner_zip_file_name = self.package.zipname try: inner_zip_name = os.path.join(tmpdir, inner_zip_file_name) inner_zip = ZipFile(inner_zip_name, "w") self.add_dir_to_zip(inner_zip, Path(self.output_dir)) inner_zip.close() outer_zip = ZipFile(self.file_obj, "w") self.add_dir_to_zip(outer_zip, Path(self.output_dir)) self.add_dir_to_zip(outer_zip, Path(tmpdir)) outer_zip.close() finally: shutil.rmtree(tmpdir) def add_dir_to_zip(self, zipped, path, rel_path=Path(".")): """ Recursively adds the dir in path + relpath and all its child dirs to zipped """ for scormFile in (path / rel_path).files(): zipped.write(scormFile, rel_path / scormFile.basename(), ZIP_DEFLATED) for directory in (path / rel_path).dirs(): self.add_dir_to_zip(zipped, path, rel_path / directory.basename()) def copy_style_files(self): """Copy style fiels to the export package""" style_files = [ "%s/../base.css" % self.style_dir, "%s/../popup_bg.gif" % self.style_dir ] style_files += self.style_dir.files("*.css") style_files += self.style_dir.files("*.jpg") style_files += self.style_dir.files("*.gif") style_files += self.style_dir.files("*.svg") style_files += self.style_dir.files("*.png") style_files += self.style_dir.files("*.js") style_files += self.style_dir.files("*.html") self.style_dir.copylist(style_files, self.output_dir) if (self.style_dir / "img").exists(): (self.style_dir / "img").copytree(self.output_dir / "img") if (self.style_dir / "js").exists(): (self.style_dir / "js").copytree(self.output_dir / "js") if (self.style_dir / "fonts").exists(): (self.style_dir / "fonts").copytree(self.output_dir / "fonts") def copy_licence(self): """Copy licence file""" if self.package.license == "GNU Free Documentation License": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(self.output_dir / 'fdl.html') def copy_files(self): """ Copy all the files used by the website. """ # Copy the style sheet files to the output dir self.copy_style_files() self.copy_resources() self.scripts_dir.copylist( ('libot_drag.js', 'bower_components/jquery/jquery.js'), self.output_dir) self.copy_players() self.copy_licence() self.copy_json() def create_pages(self, additional_kwargs=None): additional_kwargs = additional_kwargs or {} self.pages.append( self.page_class(self.package.root, 1, exporter=self, **additional_kwargs)) self.generate_pages(self.package.root, 1, additional_kwargs) def save_pages(self): for page in self.pages: page.save(self.output_dir) def copy_players(self): has_flowplayer = False has_magnifier = False has_xspfplayer = False is_break = False for page in self.pages: if is_break: break for idevice in page.node.idevices.all(): resources = idevice.as_child().system_resources if has_flowplayer and has_magnifier and has_xspfplayer: is_break = True break if not has_flowplayer: if 'flowPlayer.swf' in resources: has_flowplayer = True if not has_magnifier: if 'magnifier.swf' in resources: has_magnifier = True if not has_xspfplayer: if 'xspf_player.swf' in resources: has_xspfplayer = True def copy_resources(self): view_media = set() for page in self.pages: view_media = view_media.union(page.view_media._js). \ union(page.view_media._css.get('all', [])) view_media = [ unquote(medium.replace(settings.STATIC_URL, "")) for medium in view_media if not "tinymce" in medium ] Path(settings.STATIC_ROOT).copylist(view_media, self.output_dir) for x in self.package.resources: if settings.WIKI_CACHE_DIR in x: self.wiki_media.add(x) else: self.nonwiki_media.add(x) self.media_dir.copylist(self.nonwiki_media, self.output_dir) self.media_root.copylist(self.wiki_media, self.output_dir) def generate_pages(self, node, depth, kwargs=None): """ Recursively generate pages and store in pages member variable for retrieving later. Kwargs will be used at page creation. """ kwargs = kwargs or {} for child in node.children.all(): page = self.page_class(child, depth, exporter=self, has_children=child.children.exists(), **kwargs) last_page = self.pages[-1] if self.pages else None if last_page: page.prev_page = last_page last_page.next_page = page self.pages.append(page) self.generate_pages(child, depth + 1) def _cleanup_dict(self, dic): return dict([(x, y) for x, y in dic.items() if not x.startswith('_')]) def dict_of_node(self, node): print(node.id) node_dict = self._cleanup_dict(node.__dict__) child_list = [] if node.children.count(): i = 0 for child in node.children.all(): i = i + 1 print(i) child_list.append(self.dict_of_node(child)) node_dict['children'] = child_list node_dict['idevices'] = [] for idevice in node.idevices.all(): child = idevice.as_child() # add todict for every idevice clean_dict = child.to_dict() node_dict['idevices'].append(clean_dict) return node_dict def create_json(self): print("json") dict_for_json = self._cleanup_dict(self.package.to_dict()) dict_for_json['files'] = [] for f in self.wiki_media: dict_for_json['files'].append(f) for f in self.nonwiki_media: dict_for_json['files'].append(f) for node in self.package.nodes.all(): dict_for_json['nodes'] = [] dict_for_json['nodes'].append(self.dict_of_node(node)) with open(self.json_file, "w") as out: out.write(json.dumps(dict_for_json)) def copy_json(self): self.create_json() Path.copyfile(self.json_file, Path.joinpath(self.output_dir, Path("a.json"))) def create_temp_json_file(self): f = tempfile.NamedTemporaryFile(mode='w+t', suffix='.json', prefix='', delete=False) _filename = f.name f.close() return _filename
def _copy_resources_from_zip(self, list, dir, pack): wiki_dir = Path(os.path.join(settings.MEDIA_ROOT, settings.WIKI_CACHE_DIR)) nonwiki_dir = Path(pack.user.profile.media_path) for f in list: f = Path(f).name f = Path(os.path.join(dir, f)) if f.name.startswith("wiki__"): f2 = Path.joinpath(wiki_dir, Path(f.name)) if Path.exists(wiki_dir) is False: wiki_dir.mkdir() if Path.exists(f2) is False: Path.copyfile(f, f2) else: f2 = Path.joinpath(nonwiki_dir, Path(f.name)) if Path.exists(nonwiki_dir) is False: nonwiki_dir.mkdir() if Path.exists(f2) is False: try: Path.copyfile(f, f2) except FileNotFoundError: # some icons may be missing pass