def _uploadInto(self, os_folderpath, zope_container, clean=False, create_zope_folder=True): """ upload all files in 'os_folderpath' into 'zope_container' """ folders_to_skip = 'examples', 'CVS', '_template' # basename assert os.path.isdir( os_folderpath), "os_folderpath is not a filesystem directory" basename = os_folderpath.split(os.path.sep)[-1] zope_container_base = getattr(zope_container, 'aq_base', zope_container) if clean and hasattr(zope_container_base, basename): zope_container.manage_delObjects([basename]) if create_zope_folder: if not hasattr(zope_container_base, basename): zope_container.manage_addFolder(basename) container = getattr(zope_container, basename) else: container = zope_container for o in os.listdir(os_folderpath): os_folderpath_o = os.path.join(os_folderpath, o) if os.path.isdir(os_folderpath_o): if o not in folders_to_skip: self._uploadInto(os_folderpath_o, container, clean=clean) else: content_buffer = open(os_folderpath_o, 'rb') if clean and hasattr(getattr(container, 'aq_base', container), o): # delete it first container.manage_delObjects([o]) if hasattr(getattr(container, 'aq_base', container), o): # it already exists if DEBUG: print "++SKIP++", o, "because it already exists" #print "\t", o in container.objectIds() continue if o.endswith('.js'): try: self._uploadJavaScriptDTMLDocument( container, o, content_buffer) except Exception, m: _t = "_uploadJavaScriptDTMLDocument(%r, %r," _t = _t % (container.absolute_url_path(), o) debug(_t, 1) raise Exception, m elif o.endswith('.css'): self._uploadCSSDTMLDocument(container, o, content_buffer) elif anyTrue(o.lower().endswith, ('jpg', 'gif', 'png')): self._uploadImage(container, o, content_buffer)
class TinyMCE(Folder): """ TinyMCE of ZTinyMCE """ meta_type = METATYPE_TINYMCE security = ClassSecurityInfo() _properties = ( { 'id': 'title', 'type': 'string', 'mode': 'w' }, { 'id': 'use_gzip', 'type': 'boolean', 'mode': 'w', 'label': 'Use GZip compression' }, { 'id': 'zipfile_used', 'type': 'string', 'mode': 'r' }, { 'id': 'last_update_date', 'type': 'date', 'mode': 'r' }, ) manage_options = Folder.manage_options[:1] + ({ 'label': 'Update', 'action': 'manage_Update' }, ) + Folder.manage_options[1:] this_package_home = package_home(globals()) # legacy: by default this is false use_gzip = False def __init__(self, id, title=''): """ init """ self.id = id self.title = title self.last_update_date = None self.zipfile_used = TINYMCE_ZIPFILE self.use_gzip = False def _updateLastUpdateDate(self): self.last_update_date = DateTime() def _updateZipefileUsed(self): self.zipfile_used = TINYMCE_ZIPFILE def canUpgradeClean(self): """ return true if the zipfile used to deploy this ZTinyMCE is different from the current one """ return getattr(self, 'zipfile_used', '') != TINYMCE_ZIPFILE def getId(self): """ return id """ return self.id def getTitle(self): """ return title """ return self.title def getVersion(self): """ return __version__ """ return __version__ def doDebug(self): """ return DEBUG """ return DEBUG def useGZip(self): return self.use_gzip def doCache(self, hours=10): """ set cache headers on this request if not in debug mode """ if not self.doDebug() and hours > 0: response = self.REQUEST.RESPONSE response.setHeader('Expires', rfc1123_date(time() + 3600 * hours)) response.setHeader('Cache-Control', 'public,max-age=%d' % int(3600 * hours)) security.declareProtected(MANAGE_CONFIGURATION, 'Update') def Update(self, clean=False, REQUEST=None): """ take everything inside the 'tinymce' folder and instanciate in this instance. """ producthome = package_home(globals()) try: # 1. Create temp dir tmpdir = tempfile.mkdtemp() # 2. unpack tinymce Utils.extract(os.path.join(producthome, TINYMCE_ZIPFILE), tmpdir) # 3. unpack language pack (if exists) lpackage = os.path.join(producthome, LPACKAGE_ZIPFILE) if os.path.isfile(lpackage): Utils.extract(lpackage, tmpdir) # 4. Unravel into zope self._uploadInto(tmpdir, self, clean=clean, create_zope_folder=0) finally: # 5. Remove the unpacked dir if os.path.isdir(tmpdir): shutil.rmtree(tmpdir) self._updateLastUpdateDate() if clean: self._updateZipefileUsed() if REQUEST is not None: url = self.absolute_url() + '/manage_Update' url += '?manage_tabs_message=Update+finished' REQUEST.RESPONSE.redirect(url) def _uploadInto(self, os_folderpath, zope_container, clean=False, create_zope_folder=True): """ upload all files in 'os_folderpath' into 'zope_container' """ folders_to_skip = 'examples', 'CVS', '_template' # basename assert os.path.isdir( os_folderpath), "os_folderpath is not a filesystem directory" basename = os_folderpath.split(os.path.sep)[-1] zope_container_base = getattr(zope_container, 'aq_base', zope_container) if clean and hasattr(zope_container_base, basename): zope_container.manage_delObjects([basename]) if create_zope_folder: if not hasattr(zope_container_base, basename): zope_container.manage_addFolder(basename) container = getattr(zope_container, basename) else: container = zope_container for o in os.listdir(os_folderpath): os_folderpath_o = os.path.join(os_folderpath, o) if os.path.isdir(os_folderpath_o): if o not in folders_to_skip: self._uploadInto(os_folderpath_o, container, clean=clean) else: content_buffer = open(os_folderpath_o, 'rb') if clean and hasattr(getattr(container, 'aq_base', container), o): # delete it first container.manage_delObjects([o]) if hasattr(getattr(container, 'aq_base', container), o): # it already exists if DEBUG: print "++SKIP++", o, "because it already exists" #print "\t", o in container.objectIds() continue if o.endswith('.js'): try: self._uploadJavaScriptDTMLDocument( container, o, content_buffer) except Exception, m: _t = "_uploadJavaScriptDTMLDocument(%r, %r," _t = _t % (container.absolute_url_path(), o) debug(_t, 1) raise Exception, m elif o.endswith('.css'): self._uploadCSSDTMLDocument(container, o, content_buffer) elif anyTrue(o.lower().endswith, ('jpg', 'gif', 'png')): self._uploadImage(container, o, content_buffer) elif anyTrue(o.lower().endswith, ('html', 'htm')): self._uploadHTMLDTMLDocument(container, o, content_buffer)
def registerCSSFile(product, filename, epath=None, Globals=globals(), rel_path='css', slim_if_possible=True, gzip_if_possible=False, set_expiry_header=False, max_age_development=60, max_age_production=3600, expand_data64=False, replace_images_with_aliases=False): p_home = package_home(Globals) # product home if filename.count('-slimmed.css'): raise SystemError, "Again!??!" objectid = filename path = "%s/" % rel_path if epath: path = "%s/%s/" % (rel_path, epath) filepath = '%s%s' % (path, filename) if len(filename.split(',')) > 1: # it's a combo name!! real_filepath = _getAutogeneratedFilepath(os.path.join(p_home, filepath)) out = open(real_filepath, 'w') mtimes = [] for filepath_ in [os.path.join(p_home, '%s%s' % (path, x)) for x in filename.split(',')]: content = open(filepath_).read() if slim_if_possible and css_slimmer and not dont_slim_file(filepath_): content = css_slimmer(content) out.write(content+'\n') mtimes.append(os.stat(filepath_)[stat.ST_MTIME]) out.close() filepath = real_filepath mtime = max(mtimes) # since we've taken the slimming thought into account already # here in the loop there is no need to consider slimming the # content further down. slim_if_possible = False else: mtime = os.stat(os.path.join(p_home, filepath))[stat.ST_MTIME] setattr(product, objectid, BetterImageFile(filepath, Globals, set_expiry_header=set_expiry_header, max_age_development=max_age_development, max_age_production=max_age_production) ) obj = getattr(product, objectid) if slim_if_possible and dont_slim_file(os.path.join(p_home, filepath)): slim_if_possible = False if slim_if_possible and \ os.path.isfile(os.path.join(p_home, filepath)): if os.path.isfile(os.path.join(p_home, filepath+'.nogzip')): gzip_if_possible = False if css_slimmer is not None and slim_if_possible: slimmed = css_slimmer(open(obj.path,'rb').read()) filepath = _getAutogeneratedFilepath(obj.path + '-slimmed.css') open(filepath, 'wb').write(slimmed) setattr(obj, 'path', filepath) if expand_data64: # If this is true, then try to convert things like # 'DATA64(www/img.gif)' into # 'data:image/gif;base64,ASIDJADIJAIW00100.... ...\n' # This feature is highly experimental and has proved problematic # since it sometimes just doesn't work and it's really hard to # debug why certain images aren't working. Use carefully. # # The spec is here: http://tools.ietf.org/html/rfc2397 # The inspiration came from here: # http://developer.yahoo.com/performance/rules.html#num_http new_content = False content = file(obj.path).read() for whole_tag, path, extension in DATA64_REGEX.findall(content): fp = os.path.join(p_home, path) content = content.replace(whole_tag, 'data:image/%s;base64,%s' % \ (extension, encodestring(file(fp,'rb').read()).replace('\n','\\n'))) new_content = content if new_content: filepath = _getAutogeneratedFilepath(obj.path + '-data64expanded') open(filepath, 'wb').write(new_content) setattr(obj, 'path', filepath) if replace_images_with_aliases: # This feature opens the CSS content and looks for things like # url(/misc_/MyProduct/close.png) and replaces that with # url(/misc_/MyProduct/close.1223555.png) if possible. new_content = False if getattr(product, 'misc_infinite_aliases', {}): content = file(obj.path).read() images = [] if content.count('/misc_/'): filenames = [] for org, alias in product.misc_infinite_aliases.items(): if anyTrue(org.endswith, ('.gif','.jpg','.png')): filenames.append(org) regex = 'url\(["\']*/misc_/%s/(' % product + \ '|'.join([re.escape(x) for x in filenames]) + \ ')["\']*\)' regex = re.compile(regex) def replacer(g): whole = g.group() better_filename = product.misc_infinite_aliases.get(g.groups()[0], g.groups()[0]) whole = whole.replace(g.groups()[0], better_filename) return whole new_content = regex.sub(replacer, content) else: def replacer(match): filepath, filename = match.groups()[0].rsplit('/', 1) try: image_product = _find_related_context(product, filepath) except AttributeError: #import warnings import logging logging.warn("Unable to find image product of %s from %r" % \ (product, filepath)) return match.group() aliased = getattr(image_product, 'misc_infinite_aliases', {}).get(filename) if aliased: return match.group().replace(filename, aliased) else: return match.group() #new_content = content new_content = referred_css_images_regex.sub(replacer, content) if new_content: filepath = _getAutogeneratedFilepath(obj.path + '-aliased.css') open(filepath, 'wb').write(new_content) setattr(obj, 'path', filepath) # set up an alias too with near infinit max_age a, b = os.path.splitext(filename) objectid_alias = a + '.%s' % mtime + b setattr(product, objectid_alias, BetterImageFile(obj.path, Globals, set_expiry_header=set_expiry_header, max_age_development=EXPIRY_INFINITY, # 5 years max_age_production=EXPIRY_INFINITY # 5 years ) ) # make a note of the alias if hasattr(product, 'misc_infinite_aliases'): aliases = product.misc_infinite_aliases else: aliases = {} if objectid in aliases: # this is not supposed to happen in the same sense that you can't have # two files by the same name in the same directory if getEnvBool('PREVENT_DUPLICATE_STATIC_STORAGE', False): # by default we don't worry about that much raise ValueError, "%r is already defined in %s.misc_infinite_aliases" %\ (objectid, product) aliases[objectid] = objectid_alias setattr(product, 'misc_infinite_aliases', aliases) if gzip_if_possible: setattr(product, objectid, GzippedFile(filepath, Globals, set_expiry_header=set_expiry_header, max_age_development=max_age_development, max_age_production=max_age_production) ) # also set up the alias which overwrites the previously # set up alias. setattr(product, objectid_alias, GzippedFile(filepath, Globals, set_expiry_header=set_expiry_header, max_age_development=EXPIRY_INFINITY, max_age_production=EXPIRY_INFINITY) )