예제 #1
0
    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)
예제 #2
0
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)
예제 #3
0
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)
                )