def action_edit(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') message = '' theme = self.get_theme(self.section.path_params[0]) if self.section.handler.request.get('submit'): new_namespace = self.section.handler.request.get('namespace') if not new_namespace: message = '<div class="status error">Namespace is required</div>' elif new_namespace != theme.namespace and new_namespace in self.theme_namespaces: message = '<div class="status error">%s is already a custom theme namespace</div>' % new_namespace elif new_namespace != theme.namespace and is_local_theme_namespace( new_namespace): message = '<div class="status error">"%s" is a local theme namespace</div>' % new_namespace elif new_namespace != theme.namespace: for t in theme.body_template_names: section.rename_theme_namespace_template( theme.namespace + '/' + t, new_namespace + '/' + t) self.theme_namespaces[self.theme_namespaces.index( theme.namespace)] = new_namespace self.update() theme.namespace = new_namespace theme.put() cache.flush_all( ) # Flush all cached resources for this theme which is important for sections where it is active raise Exception('Redirect', self.section.action_redirect_path) else: raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control( control(self.section, 'text', 'namespace', theme.namespace)) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '%s<h2>Edit namespace</h2>%s' % (message, unicode(f))
def action_edit(self): if not self.section.path_params or len(self.section.path_params) != 1: raise Exception('NotFound') message = '' theme = self.get_theme(self.section.path_params[0]) if self.section.handler.request.get('submit'): new_namespace = self.section.handler.request.get('namespace') if not new_namespace: message = '<div class="status error">Namespace is required</div>' elif new_namespace != theme.namespace and new_namespace in self.theme_namespaces: message = '<div class="status error">%s is already a custom theme namespace</div>' % new_namespace elif new_namespace != theme.namespace and is_local_theme_namespace(new_namespace): message = '<div class="status error">"%s" is a local theme namespace</div>' % new_namespace elif new_namespace != theme.namespace: for t in theme.body_template_names: section.rename_theme_namespace_template(theme.namespace + '/' + t, new_namespace + '/' + t) self.theme_namespaces[self.theme_namespaces.index(theme.namespace)] = new_namespace self.update() theme.namespace = new_namespace theme.put() cache.flush_all() # Flush all cached resources for this theme which is important for sections where it is active raise Exception('Redirect', self.section.action_redirect_path) else: raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'text', 'namespace', theme.namespace)) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '%s<h2>Edit namespace</h2>%s' % (message, unicode(f))
def import_compressed_theme_data(self, data): compressed = zipfile.ZipFile(StringIO(data), 'r') paths = compressed.namelist() namespaces = [] main_dir = None for nl in paths: if nl.count('/') == 2: main_dir, nl, _ = nl.split('/') namespaces.append(nl) if not namespaces: raise Exception('No namespaces indentified') else: messages = [] for namespace in namespaces: i = 2 suffix = '' while is_local_theme_namespace(namespace + suffix): suffix = ' ' + str(i) i += 1 while namespace + suffix in self.theme_namespaces: suffix = ' ' + str(i) i += 1 calculated_namespace = namespace + suffix theme = Theme(namespace=calculated_namespace) for p in paths: if p.startswith(main_dir + '/' + namespace + '/templates/') and p.endswith('.body'): filename = p.split(main_dir + '/' + namespace + '/templates/')[1][:-5] theme.body_template_names.append(filename) theme.body_template_contents.append(validated_body_template(zipfile.ZipFile.read(compressed, p))) elif p.startswith(main_dir + '/' + namespace + '/css/') and p.endswith('.css'): filename = p.split(main_dir + '/' + namespace + '/css/')[1] theme.css_filenames.append(filename) theme.css_contents.append(zipfile.ZipFile.read(compressed, p)) elif p.startswith(main_dir + '/' + namespace + '/js/') and p.endswith('.js'): filename = p.split(main_dir + '/' + namespace + '/js/')[1] theme.js_filenames.append(filename) theme.js_contents.append(zipfile.ZipFile.read(compressed, p)) elif p.startswith(main_dir + '/' + namespace + '/images/') and p != main_dir + '/' + namespace + '/images/': filename = p.split(main_dir + '/' + namespace + '/images/')[1] content_type, _ = mimetypes.guess_type(filename) data = zipfile.ZipFile.read(compressed, p) handle = files.blobstore.create(mime_type=content_type, _blobinfo_uploaded_filename=filename) with files.open(handle, 'a') as f: f.write(data) files.finalize(handle) key = files.blobstore.get_blob_key(handle) theme.image_filenames.append(filename) theme.image_keys.append(key) key = theme.put() self.theme_keys.append(key) self.theme_namespaces.append(calculated_namespace) self.update() if messages: raise Exception(messages)
def import_compressed_theme_data(self, data): compressed = zipfile.ZipFile(StringIO(data), 'r') paths = compressed.namelist() namespaces = [] main_dir = None for nl in paths: if nl.count('/') == 2: main_dir, nl, _ = nl.split('/') namespaces.append(nl) if not namespaces: raise Exception('No namespaces indentified') else: messages = [] for namespace in namespaces: i = 2 suffix = '' while is_local_theme_namespace(namespace + suffix): suffix = ' ' + str(i) i += 1 while namespace + suffix in self.theme_namespaces: suffix = ' ' + str(i) i += 1 calculated_namespace = namespace + suffix theme = Theme(namespace=calculated_namespace) for p in paths: if p.startswith(main_dir + '/' + namespace + '/templates/') and p.endswith('.body'): filename = p.split(main_dir + '/' + namespace + '/templates/')[1][:-5] theme.body_template_names.append(filename) theme.body_template_contents.append(validated_body_template(db.Text(zipfile.ZipFile.read(compressed, p)))) elif p.startswith(main_dir + '/' + namespace + '/css/') and p.endswith('.css'): filename = p.split(main_dir + '/' + namespace + '/css/')[1] theme.css_filenames.append(filename) theme.css_contents.append(db.Text(zipfile.ZipFile.read(compressed, p))) elif p.startswith(main_dir + '/' + namespace + '/js/') and p.endswith('.js'): filename = p.split(main_dir + '/' + namespace + '/js/')[1] theme.js_filenames.append(filename) theme.js_contents.append(db.Text(zipfile.ZipFile.read(compressed, p))) elif p.startswith(main_dir + '/' + namespace + '/images/') and p != main_dir + '/' + namespace + '/images/': filename = p.split(main_dir + '/' + namespace + '/images/')[1] content_type, _ = mimetypes.guess_type(filename) data = db.Blob(zipfile.ZipFile.read(compressed, p)) key = File(filename=filename, data=data, content_type=content_type, section_path=self.section.path).put() theme.image_filenames.append(filename) theme.image_keys.append(str(key)) key = theme.put() self.theme_keys.append(str(key)) self.theme_namespaces.append(calculated_namespace) self.update() if messages: raise Exception(messages)
def action_add(self): message = '' if self.section.handler.request.get('submit'): namespace = self.section.handler.request.get('namespace').replace('/', '') if not namespace: message = '<div class="status error">Namespace is required</div>' elif namespace in self.theme_namespaces: message = '<div class="status error">Namespace "%s" already exists</div>' % namespace elif is_local_theme_namespace(namespace): message = '<div class="status error">Namespace "%s" is already a local theme namespace</div>' % namespace else: key = Theme(namespace=namespace).put() self.theme_keys.append(key) self.theme_namespaces.append(namespace) self.update() raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control(control(self.section, 'text', 'namespace', '', 'Namespace')) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '%s<h2>Add theme</h2>%s' % (message, unicode(f))
def action_add(self): message = '' if self.section.handler.request.get('submit'): namespace = self.section.handler.request.get('namespace').replace( '/', '') if not namespace: message = '<div class="status error">Namespace is required</div>' elif namespace in self.theme_namespaces: message = '<div class="status error">Namespace "%s" already exists</div>' % namespace elif is_local_theme_namespace(namespace): message = '<div class="status error">Namespace "%s" is already a local theme namespace</div>' % namespace else: key = Theme(namespace=namespace).put() self.theme_keys.append(key) self.theme_namespaces.append(namespace) self.update() raise Exception('Redirect', self.section.action_redirect_path) f = form(self.section, self.section.full_path) f.add_control( control(self.section, 'text', 'namespace', '', 'Namespace')) f.add_control(control(self.section, 'submit', 'submit', 'Submit')) return '%s<h2>Add theme</h2>%s' % (message, unicode(f))
def get(self, path): try: path = path.strip('/') path, extension = os.path.splitext(path) contents = cache.get(path + extension) last_modified = cache.get(CACHE_LAST_MODIFIED_PREPEND + path + extension) if not contents: contents = '' ''' YUI ''' yui_parts = '' if path.find('___yui___') < 0 else path[path.find('___yui___'):].replace('___yui___', '', 1) yui_parts = yui_parts if yui_parts.find('___') < 0 else yui_parts[:yui_parts.find('___')] rest_parts = path.replace('___yui___', '', 1).replace(yui_parts, '', 1).replace('___local___', '', 1) if '___theme___' in rest_parts: local_parts, theme_parts = rest_parts.split('___theme___') else: local_parts, theme_parts = rest_parts, None if yui_parts: yui_version = '3.7.2/build/' yui_absolute = 'http://yui.yahooapis.com/combo?' yui_parts = yui_parts.split('__') yui_parts = [(yui_version + x.replace('_', '/') + '-min' + extension) for x in yui_parts] result = urlfetch.fetch(yui_absolute + '&'.join(yui_parts)) if result.status_code == 200: contents += result.content else: raise Exception('NotFound') ''' Local ''' filenames = [(x + extension) for x in local_parts.split('_')] if len(filenames) != len(utils.unique_list(filenames)): raise Exception('NotFound') files = utils.file_search(filenames) if extension == '.css': contents += (''.join([parse_content(open(f, 'r').read(), True) for f in files])) else: contents += (''.join([parse_content(open(f, 'r').read()) for f in files])) ''' Theme ''' if theme_parts: theme_namespace, theme_parts = theme_parts.split('___') filenames = [(x + extension) for x in theme_parts.split('_')] if len(filenames) != len(utils.unique_list(filenames)): raise Exception('NotFound') elif is_local_theme_namespace(theme_namespace): if extension == '.css': contents += (''.join([parse_content(open('./themes/' + theme_namespace + '/' + extension.strip('.') + '/' + f, 'r').read(), True, theme_namespace) for f in filenames])) else: contents += (''.join([parse_content(open('./themes/' + theme_namespace + '/' + extension.strip('.') + '/' + f, 'r').read(), False, theme_namespace) for f in filenames])) else: t = get_custom_theme(theme_namespace) for f in filenames: if extension == '.css': index = t.css_filenames.index(f) contents += parse_content(t.css_contents[index], True, theme_namespace) elif extension == '.js': index = t.js_filenames.index(f) contents += parse_content(t.js_contents[index], False, theme_namespace) cache.set(path + extension, contents) last_modified = datetime.utcnow() cache.set(CACHE_LAST_MODIFIED_PREPEND + path + extension, last_modified) if not contents.strip(): raise Exception('NotFound') if not last_modified: last_modified = datetime.utcnow() cache.set(CACHE_LAST_MODIFIED_PREPEND + path + extension, last_modified) content_type = 'application/javascript' if extension == '.js' else 'text/css' response = webapp2.Response(template.get(contents.strip()), content_type=content_type) response.headers['Connection'] = 'Keep-Alive' response.headers['Date'] = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT") response.headers['Last-Modified'] = last_modified.strftime("%a, %d %b %Y %H:%M:%S GMT") response.headers['Expires'] = (last_modified + timedelta(8)).strftime("%a, %d %b %Y %H:%M:%S GMT") response.cache_control.no_cache = None response.cache_control.public = True response.cache_control.max_age = 604800000 # One week return response except Exception as inst: message = '' if configuration.debug_mode(): message = '<div class="status error">' + unicode(inst) + '<br><br>' + traceback.format_exc().replace('\n', '<br><br>') + '</div>' response = webapp2.Response(template.get('<html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1>Document or file requested by the client was not found.%s</body></html>' % message)) response.set_status(404) return response
def import_compressed_theme_data(self, data): compressed = zipfile.ZipFile(StringIO(data), 'r') paths = compressed.namelist() namespaces = [] main_dir = None for nl in paths: if nl.count('/') == 2: main_dir, nl, _ = nl.split('/') namespaces.append(nl) if not namespaces: raise Exception('No namespaces indentified') else: messages = [] for namespace in namespaces: i = 2 suffix = '' while is_local_theme_namespace(namespace + suffix): suffix = ' ' + str(i) i += 1 while namespace + suffix in self.theme_namespaces: suffix = ' ' + str(i) i += 1 calculated_namespace = namespace + suffix theme = Theme(namespace=calculated_namespace) for p in paths: if p.startswith(main_dir + '/' + namespace + '/templates/') and p.endswith('.body'): filename = p.split(main_dir + '/' + namespace + '/templates/')[1][:-5] theme.body_template_names.append(filename) theme.body_template_contents.append( validated_body_template( zipfile.ZipFile.read(compressed, p))) elif p.startswith(main_dir + '/' + namespace + '/css/') and p.endswith('.css'): filename = p.split(main_dir + '/' + namespace + '/css/')[1] theme.css_filenames.append(filename) theme.css_contents.append( zipfile.ZipFile.read(compressed, p)) elif p.startswith(main_dir + '/' + namespace + '/js/') and p.endswith('.js'): filename = p.split(main_dir + '/' + namespace + '/js/')[1] theme.js_filenames.append(filename) theme.js_contents.append( zipfile.ZipFile.read(compressed, p)) elif p.startswith( main_dir + '/' + namespace + '/images/' ) and p != main_dir + '/' + namespace + '/images/': filename = p.split(main_dir + '/' + namespace + '/images/')[1] content_type, _ = mimetypes.guess_type(filename) data = zipfile.ZipFile.read(compressed, p) handle = files.blobstore.create( mime_type=content_type, _blobinfo_uploaded_filename=filename) with files.open(handle, 'a') as f: f.write(data) files.finalize(handle) key = files.blobstore.get_blob_key(handle) theme.image_filenames.append(filename) theme.image_keys.append(key) key = theme.put() self.theme_keys.append(key) self.theme_namespaces.append(calculated_namespace) self.update() if messages: raise Exception(messages)
def get(self, path): try: path = path.strip('/') path, extension = os.path.splitext(path) contents = cache.get(path + extension) last_modified = cache.get(CACHE_LAST_MODIFIED_PREPEND + path + extension) if not contents: contents = '' ''' YUI ''' yui_parts = '' if path.find('___yui___') < 0 else path[ path.find('___yui___'):].replace('___yui___', '', 1) yui_parts = yui_parts if yui_parts.find( '___') < 0 else yui_parts[:yui_parts.find('___')] rest_parts = path.replace('___yui___', '', 1).replace( yui_parts, '', 1).replace('___local___', '', 1) if '___theme___' in rest_parts: local_parts, theme_parts = rest_parts.split('___theme___') else: local_parts, theme_parts = rest_parts, None if yui_parts: yui_version = '3.7.2/build/' yui_absolute = 'http://yui.yahooapis.com/combo?' yui_parts = yui_parts.split('__') yui_parts = [(yui_version + x.replace('_', '/') + '-min' + extension) for x in yui_parts] result = urlfetch.fetch(yui_absolute + '&'.join(yui_parts)) if result.status_code == 200: contents += result.content else: raise Exception('NotFound') ''' Local ''' filenames = [(x + extension) for x in local_parts.split('_')] if len(filenames) != len(utils.unique_list(filenames)): raise Exception('NotFound') files = utils.file_search(filenames) if extension == '.css': contents += (''.join([ parse_content(open(f, 'r').read(), True) for f in files ])) else: contents += (''.join( [parse_content(open(f, 'r').read()) for f in files])) ''' Theme ''' if theme_parts: theme_namespace, theme_parts = theme_parts.split('___') filenames = [(x + extension) for x in theme_parts.split('_')] if len(filenames) != len(utils.unique_list(filenames)): raise Exception('NotFound') elif is_local_theme_namespace(theme_namespace): if extension == '.css': contents += (''.join([ parse_content( open( './themes/' + theme_namespace + '/' + extension.strip('.') + '/' + f, 'r').read(), True, theme_namespace) for f in filenames ])) else: contents += (''.join([ parse_content( open( './themes/' + theme_namespace + '/' + extension.strip('.') + '/' + f, 'r').read(), False, theme_namespace) for f in filenames ])) else: t = get_custom_theme(theme_namespace) for f in filenames: if extension == '.css': index = t.css_filenames.index(f) contents += parse_content( t.css_contents[index], True, theme_namespace) elif extension == '.js': index = t.js_filenames.index(f) contents += parse_content( t.js_contents[index], False, theme_namespace) cache.set(path + extension, contents) last_modified = datetime.utcnow() cache.set(CACHE_LAST_MODIFIED_PREPEND + path + extension, last_modified) if not contents.strip(): raise Exception('NotFound') if not last_modified: last_modified = datetime.utcnow() cache.set(CACHE_LAST_MODIFIED_PREPEND + path + extension, last_modified) content_type = 'application/javascript' if extension == '.js' else 'text/css' response = webapp2.Response(template.get(contents.strip()), content_type=content_type) response.headers['Connection'] = 'Keep-Alive' response.headers['Date'] = datetime.utcnow().strftime( "%a, %d %b %Y %H:%M:%S GMT") response.headers['Last-Modified'] = last_modified.strftime( "%a, %d %b %Y %H:%M:%S GMT") response.headers['Expires'] = ( last_modified + timedelta(8)).strftime("%a, %d %b %Y %H:%M:%S GMT") response.cache_control.no_cache = None response.cache_control.public = True response.cache_control.max_age = 604800000 # One week return response except Exception as inst: message = '' if configuration.debug_mode(): message = '<div class="status error">' + unicode( inst) + '<br><br>' + traceback.format_exc().replace( '\n', '<br><br>') + '</div>' response = webapp2.Response( template.get( '<html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1>Document or file requested by the client was not found.%s</body></html>' % message)) response.set_status(404) return response