def __init__(self, code, channel, symbols=None, doctest=False, username=None): threading.Thread.__init__(self) self.code = trim_empty_lines_from_end(code) + "\n" # the extra new line character at the end above prevents a syntax error # if the last line is a comment. self.channel = channel if username is not None: self.username = username self.friendly = config[self.username]["friendly"] else: try: pageid = self.channel.split("_")[0] self.username = names[pageid] self.friendly = config[self.username]["friendly"] except: self.friendly = False print("Exception raised in Interpreter.init(); channel = %s" % self.channel) try: u_print("username = "******"username not defined...") self.username = None try: u_print("pageid in names: ", self.channel.split("_")[0] in names) except: pass self.symbols = {} if symbols is not None: self.symbols.update(symbols) self.doctest = doctest if self.doctest: self.doctest_out = StringIO() self.symbols["doctest_out"] = self.doctest_out
def save_file_python_interpreter_request_handler(request): '''extracts the path & the file content from the request and saves the content in the path as indicated.''' if DEBUG: print("Entering save_file_python_interpreter_request_handler.") if python_version >= 3: request.data = request.data.decode('utf-8') data = request.data request.send_response(200) request.end_headers() info = data.split("_::EOF::_") path = info[1] if python_version < 3: try: path = path.encode(sys.getfilesystemencoding()) except: print(" Could not encode path.") content = '_::EOF::_'.join(info[2:]) save_file(path, content) if DEBUG: u_print("info =", info) if info[0]: username = request.crunchy_username config[username]['alternate_python_version'] = info[0] # the following updates the value stored in configuration.defaults config[username]['_set_alternate_python_version'](info[0]) return path
def _save_settings(self, name=None, value=None, initial=False): '''Update user settings and save results to a configuration file''' if name is not None: # otherwise, we need to save all... self._preferences[name] = value if initial: return if name == 'language': self._select_language(value) if self._not_loaded: # saved configuration not retrieved; do not overwrite return # update values of non-properties self._preferences['site_security'] = self.site_security #self._preferences['styles'] = self.styles self._preferences['_modification_rules'] = self._modification_rules saved = {} for name in self._preferences: if not (name in self._not_saved or name.startswith('_')): saved[name] = self._preferences[name] saved['_modification_rules'] = self._modification_rules pickled_path = os.path.join(self.user_dir, settings_path) try: pickled = open(pickled_path, 'wb') except: u_print("Could not open file in configuration._save_settings().") return pickle.dump(saved, pickled, protocol=2) pickled.close() return
def _get_site_security(self, site): '''determines the appropriate level of security to use for given site''' if site in self.site_security: u_print("in _get_site_security, site = ", site) return self.site_security[site] else: return 'display trusted'
def remove_rule(self, no): '''remove an existing rule''' try: del self._modification_rules[no] self._save_settings() except: u_print(_("Choose a valid rule number to remove.")) self.list_rules() return
def modify_vlam(page, elem, dummy): """modify the existing markup on a page. Restricted to changing title attribute values of an element. """ if config[page.username]["modify_markup"] is False: return if "title" not in elem.attrib: return for rule in config[page.username]["_modification_rules"]: try: elem.attrib["title"] = dispatcher[rule[0]](elem.attrib["title"], rule[1:]) except e: u_print("Error found in user_markup.modify_vlam(): ", sys.exc_info()[1]) u_print("rule = ", rule) return
def init(): '''Called when we need to initialize the various instances - based on the number of different users defined.''' for prop in interface.additional_properties: setattr(UserPreferences, prop, interface.additional_properties[prop]) skipped = [] for key in additional_vlam: try: options[key].extend(additional_vlam[key]) except: # the key might not be registered yet options[key] = [] skipped.append((key, additional_vlam[key])) # after the first pass, problematic keys should have been registered # by the plugin. for key, additional_option in skipped: try: options[key].extend(additional_option) except: u_print("Problem in config.init()") u_print("The following additional vlam option") u_print("key = %s, value= %s" % (key, additional_option)) u_print("is raising an exception.") u_print("Please file a bug report") users = {} for name in accounts: config[name] = {} users[name] = UserPreferences(config[name], name) config[name]['log'] = users[name].log config[name]['log_filename'] = os.path.join(users[name].temp_dir, 'crunchy.html') config[name]['logging_uids'] = users[name].logging_uids config[name]['symbols'] = { config[name]['_prefix']: users[name], 'temp_dir': users[name].temp_dir } config[name]['temp_dir'] = users[name].temp_dir config[name]['_get_current_page_security_level'] = users[ name]._get_current_page_security_level config[name]['_set_alternate_python_version'] = users[ name]._set_alternate_python_version config[name]['_set_local_security'] = users[name]._set_local_security config[name]['_save_settings'] = users[name]._save_settings config[name]['initial_security_set'] = False
def modify_vlam(page, elem, dummy): '''modify the existing markup on a page. Restricted to changing title attribute values of an element. ''' if config[page.username]['modify_markup'] is False: return if "title" not in elem.attrib: return for rule in config[page.username]['_modification_rules']: try: elem.attrib["title"] = dispatcher[rule[0]](elem.attrib["title"], rule[1:]) except e: u_print("Error found in user_markup.modify_vlam(): ", sys.exc_info()[1]) u_print("rule = ", rule) return
def return_template(page, elem): """determine the file to use as a template and if a new template needs to be created.""" url = elem.attrib["title"].strip().split(" ")[-1] base_dir, dummy = os.path.split(page.url) if page.is_from_root: url = os.path.normpath(os.path.join(config["crunchy_base_dir"], "server_root", base_dir[1:], url)) elif page.is_local: url = os.path.normpath(os.path.join(base_dir, url)) if url not in _templates: try: filehandle = codecs.open(url, encoding="utf8") except: u_print("In merge_with_template, can not open url =", url) traceback.print_exc() return None create_template(url, page.username, filehandle) return _templates[url]
def scan_for_unwanted(css_file): '''Looks for any suspicious code in a css file For now, any file with "url(", "&#" and other "dangerous substrings in it is deemed suspicious and will be rejected. returns True if suspicious code is found.''' global __dangerous_text for line in css_file.readlines(): squished = line.replace(' ', '').replace('\t', '') for x in dangerous_strings: if x in squished: if DEBUG: u_print("Found suspicious content in the following line:") u_print(squished) __dangerous_text = squished return True return False
def init(): '''Called when we need to initialize the various instances - based on the number of different users defined.''' for prop in interface.additional_properties: setattr(UserPreferences, prop, interface.additional_properties[prop]) skipped = [] for key in additional_vlam: try: options[key].extend(additional_vlam[key]) except: # the key might not be registered yet options[key] = [] skipped.append((key, additional_vlam[key])) # after the first pass, problematic keys should have been registered # by the plugin. for key, additional_option in skipped: try: options[key].extend(additional_option) except: u_print("Problem in config.init()") u_print("The following additional vlam option") u_print("key = %s, value= %s" %(key, additional_option)) u_print("is raising an exception.") u_print("Please file a bug report") users = {} for name in accounts: config[name] = {} users[name] = UserPreferences(config[name], name) config[name]['log'] = users[name].log config[name]['log_filename'] = os.path.join(users[name].temp_dir, 'crunchy.html') config[name]['logging_uids'] = users[name].logging_uids config[name]['symbols'] = {config[name]['_prefix']:users[name], 'temp_dir': users[name].temp_dir} config[name]['temp_dir'] = users[name].temp_dir config[name]['_get_current_page_security_level'] = users[name]._get_current_page_security_level config[name]['_set_alternate_python_version'] = users[name]._set_alternate_python_version config[name]['_set_local_security'] = users[name]._set_local_security config[name]['_save_settings'] = users[name]._save_settings config[name]['initial_security_set'] = False
def return_template(page, elem): '''determine the file to use as a template and if a new template needs to be created.''' url = elem.attrib['title'].strip().split(' ')[-1] base_dir, dummy = os.path.split(page.url) if page.is_from_root: url = os.path.normpath( os.path.join(config['crunchy_base_dir'], "server_root", base_dir[1:], url)) elif page.is_local: url = os.path.normpath(os.path.join(base_dir, url)) if url not in _templates: try: filehandle = codecs.open(url, encoding='utf8') except: u_print("In merge_with_template, can not open url =", url) traceback.print_exc() return None create_template(url, page.username, filehandle) return _templates[url]
def merge_with_template(page, elem): '''merge an html file with a template''' if 'template' not in elem.attrib['title']: return # The format we expect is # <meta title="template template_file.html"> # However, for reStructuredText files, we have instead the following: # <meta title="template" content="template_file.html"> # So, let's convert to the canonical form if possible. if elem.attrib['title'] == 'template': if 'content' not in elem.attrib: return else: elem.attrib['title'] = "template " + elem.attrib['content'] transform_rst(page) page_divs = find_divs(page) if not page_divs: u_print("No div found in page; can not merge with template.") return if page.url.startswith('http'): u_print("Merging with remote templates not implemented yet.") return template = return_template(page, elem) if template is None: u_print("No template has been found.") return merge_heads(template, page) merge_bodies(template, page, page_divs) return
def fset(obj, val): # indirectly tested '''assigns a value within an allowed set (if defined), and saves the result''' prefs = getattr(obj, "_preferences") # some properties are designed to allow any value to be set to them if ANY in allowed and val != ANY: allowed.append(val) if val not in allowed: try: current = getattr(obj, "_"+name) # can raise AttributeError # if not (yet) defined... u_print(_("%s is an invalid choice for %s.%s" % (val, prefs['_prefix'], name))) u_print(_("The valid choices are: "), allowed) u_print(_("The current value is: "), current) except AttributeError: # first time; set to default! _set_and_save(obj, name, default, initial=True) else: if val == ANY: try: current = getattr(obj, "_"+name) except: current = default val = current _only_set_and_save_if_new(obj, name, val) return
def merge_with_template(page, elem): """merge an html file with a template""" if "template" not in elem.attrib["title"]: return # The format we expect is # <meta title="template template_file.html"> # However, for reStructuredText files, we have instead the following: # <meta title="template" content="template_file.html"> # So, let's convert to the canonical form if possible. if elem.attrib["title"] == "template": if "content" not in elem.attrib: return else: elem.attrib["title"] = "template " + elem.attrib["content"] transform_rst(page) page_divs = find_divs(page) if not page_divs: u_print("No div found in page; can not merge with template.") return if page.url.startswith("http"): u_print("Merging with remote templates not implemented yet.") return template = return_template(page, elem) if template is None: u_print("No template has been found.") return merge_heads(template, page) merge_bodies(template, page, page_divs) return
def fset(obj, val): # indirectly tested '''assigns a value within an allowed set (if defined), and saves the result''' prefs = getattr(obj, "_preferences") # some properties are designed to allow any value to be set to them if ANY in allowed and val != ANY: allowed.append(val) if val not in allowed: try: current = getattr(obj, "_" + name) # can raise AttributeError # if not (yet) defined... u_print( _("%s is an invalid choice for %s.%s" % (val, prefs['_prefix'], name))) u_print(_("The valid choices are: "), allowed) u_print(_("The current value is: "), current) except AttributeError: # first time; set to default! _set_and_save(obj, name, default, initial=True) else: if val == ANY: try: current = getattr(obj, "_" + name) except: current = default val = current _only_set_and_save_if_new(obj, name, val) return
def __init__(self, code, channel, symbols = None, doctest=False, username=None): threading.Thread.__init__(self) self.code = trim_empty_lines_from_end(code) + "\n" # the extra new line character at the end above prevents a syntax error # if the last line is a comment. self.channel = channel if username is not None: self.username = username self.friendly = config[self.username]['friendly'] else: try: pageid = self.channel.split("_")[0] self.username = names[pageid] self.friendly = config[self.username]['friendly'] except: self.friendly = False print ("Exception raised in Interpreter.init(); channel = %s" % self.channel) try: u_print("username = "******"username not defined...") self.username = None try: u_print("pageid in names: ", self.channel.split("_")[0] in names) except: pass self.symbols = {} if symbols is not None: self.symbols.update(symbols) self.doctest = doctest if self.doctest: self.doctest_out = StringIO() self.symbols['doctest_out'] = self.doctest_out
def _set_site_security(self, site, choice): '''sets the security level of a given site''' if choice in options['security']: self.site_security[site] = choice self._save_settings('site_security', choice) u_print(_("site security set to: "), choice) else: u_print((_("Invalid choice for %s.site_security") % self._preferences['_prefix'])) u_print(_("The valid choices are: "), str(options['security']))
def _set_site_security(self, site, choice): '''sets the security level of a given site''' if choice in options['security']: self.site_security[site] = choice self._save_settings('site_security', choice) u_print(_("site security set to: ") , choice) else: u_print((_("Invalid choice for %s.site_security") % self._preferences['_prefix'])) u_print(_("The valid choices are: "), str(options['security']))
def open_local_file(url): if DEBUG: u_print("attempting to open file: " + url) if url.startswith("http://"): try: return urlopen(url) except: if DEBUG: u_print("Cannot open remote file with url= " + url) return False try: return open(url, mode="r") except IOError: if DEBUG2: u_print("Opening the file without encoding did not work.") try: return open(url.encode(sys.getfilesystemencoding()), mode="r") except IOError: if DEBUG: u_print("Cannot open local file with url= " + url) return False
def add_rule(self): '''interactive function to enable rules to modify markup''' u_print(_("Enter a rule method to modify markup.")) u_print(_("The allowed methods are: add_option, remove_option, replace")) method = ask_user(_("Enter method: ")).strip() if method == 'replace': to_replace = ask_user(_("Markup value to replace: ")) replacement = ask_user(_("Replacement value: ")) self._modification_rules.append([method, to_replace, replacement]) elif method == 'add_option': add = ask_user(_("Enter option to add (e.g. linenumber): ")) self._modification_rules.append([method, add]) elif method == 'remove_option': remove = ask_user(_("Enter option to remove (e.g. linenumber)")) self._modification_rules.append([method, remove]) else: u_print(_("Unknown method.")) return self._save_settings() return
def add_rule(self): '''interactive function to enable rules to modify markup''' u_print(_("Enter a rule method to modify markup.")) u_print( _("The allowed methods are: add_option, remove_option, replace")) method = ask_user(_("Enter method: ")).strip() if method == 'replace': to_replace = ask_user(_("Markup value to replace: ")) replacement = ask_user(_("Replacement value: ")) self._modification_rules.append([method, to_replace, replacement]) elif method == 'add_option': add = ask_user(_("Enter option to add (e.g. linenumber): ")) self._modification_rules.append([method, add]) elif method == 'remove_option': remove = ask_user(_("Enter option to remove (e.g. linenumber)")) self._modification_rules.append([method, remove]) else: u_print(_("Unknown method.")) return self._save_settings() return
def print_lines(self): '''Assumes all the data written is *not* binary, which is true for tests. Decodes them from UTF-8 and prints them to standard out.''' for line in self.lines: u_print(line)
def _set_dirs(self): '''sets the user directory, creating it if needed. Creates also a temporary directory''' if self.name != "Unknown User": self.user_dir = accounts[self.name][0] else: self.user_dir = os.path.join(os.path.expanduser("~"), ".crunchy") self.temp_dir = os.path.join(self._user_dir, "temp") if not os.path.exists(self.user_dir): # first time ever try: os.makedirs(self.user_dir) if not os.path.exists(self.temp_dir): try: os.makedirs(self.temp_dir) except: # Note: we do not translate diagnostic messages # sent to the terminal u_print("Created successfully home directory.") u_print("Could not create temporary directory.") self.temp_dir = self.user_dir return except: u_print("Could not create the user directory.") self.user_dir = os.getcwd() # use crunchy's as a default. self.temp_dir = os.path.join(self.user_dir, "temp") if not os.path.exists(self.temp_dir): try: os.makedirs(self.temp_dir) except: u_print("Could not create temporary directory.") self.temp_dir = self.user_dir return return # we may encounter a situation where a ".crunchy" directory # had been created by an old version without a temporary directory if not os.path.exists(self.temp_dir): try: os.makedirs(self.temp_dir) except: u_print("home directory '.crunchy' exists; however, ") u_print("could not create temporary directory.") self.temp_dir = self.user_dir return return
def is_link_safe(elem, page): '''only keep <link> referring to style sheets that are deemed to be safe''' global __dangerous_text url = page.url if DEBUG: u_print("found link element; page url = "+ url) #-- Only allow style files if "type" in elem.attrib: type = elem.attrib["type"] if DEBUG2: u_print("type = "+ type) if type.lower() != "text/css": # not a style sheet - eliminate __dangerous_text = 'type != "text/css"' return False else: if DEBUG2: u_print("type not found.") __dangerous_text = 'type not found' return False #-- if "rel" in elem.attrib: rel = elem.attrib["rel"] if DEBUG2: u_print("rel = "+ rel) if rel.lower() != "stylesheet": # not a style sheet - eliminate __dangerous_text = 'rel != "stylesheet"' return False else: if DEBUG2: u_print("rel not found.") __dangerous_text = 'rel not found' return False #-- if "href" in elem.attrib: href = elem.attrib["href"] if DEBUG2: u_print("href = "+ href) else: # no link to a style sheet: not a style sheet! if DEBUG2: u_print("href not found.") __dangerous_text = 'href not found' return False #--If we reach this point we have in principle a valid style sheet. try: link_url = find_url(url, href, page) except: u_print("problem encountered in security.py (trying link_url = find_url)") return False if DEBUG2: u_print("link url = "+ link_url) #--Scan for suspicious content suspicious = False if page.is_local: css_file = open_local_file(link_url) if not css_file: # could not open the file return False suspicious = scan_for_unwanted(css_file) elif page.is_remote: css_file = open_local_file(link_url) if not css_file: # could not open the file return False suspicious = scan_for_unwanted(css_file) else: # local page loaded via normal link. css_file = open_local_file(link_url) if not css_file: # could not open the file return False suspicious = scan_for_unwanted(css_file) if not suspicious: if DEBUG: u_print("No suspicious content found in css file.") return True elif DEBUG: u_print("Suspicious content found in css file.") return False if DEBUG: u_print("should not be reached") return False # don't take any chances
def validate_image(src, page): '''verifies that the file contents appears to be that of an image''' global root_path if DEBUG: u_print("entering validate_image") u_print("page.is_local "+ str(page.is_local)) u_print("page.is_remote "+ str(page.is_remote)) u_print("page.url "+ page.url) u_print("src "+ src) u_print("root_path "+ root_path) if src.startswith("http://"): # the image may be residing on a different site than the one # currently viewed. fn = src elif page.is_local: local_dir = os.path.split(page.url)[0] fn = os.path.join(local_dir, src) elif page.is_remote: fn = urljoin(page.url, src) else: src = urljoin(page.url, src)[1:] # porting to Python 3.1 and temporarily removing the "decoding" # - assuming plain string, which may be wrong #fn = os.path.join(root_path, src.decode('utf-8')) fn = os.path.join(root_path, src) try: if DEBUG: u_print("opening fn="+ fn) try: if page.is_remote or src.startswith("http://"): h = urlopen(fn).read(32) #32 is all that's needed for # imghrd.what else: h = open(fn.encode(sys.getfilesystemencoding()), 'rb').read(32) if DEBUG: u_print("opened the file") except: if DEBUG: u_print("could not open") return False try: type = imghdr.what('ignore', h) if DEBUG: u_print("opened with imghdr.what") u_print("image type = "+ type) u_print("image src = "+ src) if type is not None: u_print("validated image:"+ fn) return True except: if DEBUG: u_print("could not open with imghdr.what") return False except: return False
def _load_settings(self): ''' loads the user settings from a configuration file; uses default values if file specific settings is not found. ''' success = False pickled_path = os.path.join(self.user_dir, settings_path) try: pickled = open(pickled_path, 'rb') success = True except: u_print("No configuration file found.") u_print("user_dir = ", self.user_dir) if success: try: saved = pickle.load(pickled) pickled.close() except EOFError: self._not_loaded = False self._save_settings() return else: # save the file with the default value self._not_loaded = False self._save_settings() return for key in saved: try: val = UserPreferences.__dict__[key] if isinstance(val, property): val.fset(self, saved[key]) else: u_print("*" * 50) u_print("Unless Crunchy has just been updated,") u_print("this should not happen.") u_print("saved variable: %s is not a property", key) except: try: val = getattr(self, key) setattr(self, key, saved[key]) self._preferences[key] = saved[key] except: u_print("*" * 50) u_print("Unless Crunchy has just been updated,") u_print("this should not happen.") u_print("saved variable: %s is not recognized" % key) self._not_loaded = False return
def exec_external_python_version(code=None, path=None, alternate_version=True, write_over=True, username=None): """execute code in an external process with the choosed python intepreter currently works under: * Windows NT * GNOME/KDE/XFCE/xterm (Tested) * OS X """ if DEBUG: print("Entering exec_external_python_interpreter.") print("path =" + str(path)) print("alternate version = " + str(alternate_version)) if alternate_version: python_interpreter = config[username]['alternate_python_version'] else: python_interpreter = 'python' # default interpreter if path is None: path = os.path.join(config[username]['temp_dir'], "temp.py") if DEBUG: print("temp path is:") print(path) if os.name == 'nt' or sys.platform == 'darwin': current_dir = os.getcwd() target_dir, fname = os.path.split(path) if code is not None and write_over: try: filename = open(path, 'w') filename.write(code) filename.close() except: print("Could not save file in file_service.exec_external_python_version()") if os.name == 'nt': os.chdir(target_dir) # change dir so as to deal with paths that # include spaces try: Popen(["command", ('/c start %s %s' % (python_interpreter, fname))]) except: Popen(["cmd.exe", ('/c start %s %s' % (python_interpreter, fname))]) print(" Launching program did not work with command; used cmd.exe") os.chdir(current_dir) elif sys.platform == 'darwin': # a much more general method can be found # in SPE, Stani's Python Editor - Child.py activate = 'tell application "Terminal" to activate' script = r"cd '\''%s'\'';%s '\''%s'\'';exit" % (target_dir, python_interpreter, fname) do_script = r'tell application "Terminal" to do script "%s"' % script command = "osascript -e '%s';osascript -e '%s'" % (activate, do_script) os.popen(command) elif os.name == 'posix': terminals_to_try = list(linux_terminals) while terminals_to_try: (terminal, start_parameter) = terminals_to_try[0] try: if DEBUG: print('Try to launch:') u_print(terminal, start_parameter, python_interpreter, path) Popen([terminal, start_parameter, python_interpreter, path]) # If it works, remove all terminals in the to_try list terminals_to_try = [] except: if DEBUG: print('Failed') if len(terminals_to_try) == 1: # Impossible to find a terminal raise NotImplementedError else: terminals_to_try = terminals_to_try[1:] else: raise NotImplementedError
def _select_language(self, choice): '''selects the appropriate file for language translation and attempts to set editarea_language to the same value''' translate['init_translation'](choice) u_print(_("language set to: "), choice) self.editarea_language = choice
def list_rules(self): '''list the rules used to modify markup''' u_print("#", _("\tmethod"), _("\targuments")) for i, rule in enumerate(self._modification_rules): u_print(i, "\t%s" % rule[0], "\t%s" % rule[1:])
def find_url(url, href, page): '''given the url of a "parent" html page and the href of a "child" (specified in a link element), returns the complete url of the child.''' if "://" in url: if DEBUG2: u_print(":// found in url") return urljoin(url, href) elif "://" in href: if DEBUG2: u_print(":// found in href") return href if page.is_local: base, fname = os.path.split(url) href = os.path.normpath(os.path.join(base, os.path.normpath(href))) return href elif href.startswith("/"): # local css file from the root server try: href = os.path.normpath(os.path.join(root_path, os.path.normpath(href[1:]))) except: try: href = os.path.normpath(os.path.join( root_path.encode(sys.getfilesystemencoding()), os.path.normpath(href[1:]))) except: try: href = os.path.normpath(os.path.join( root_path.decode(sys.getfilesystemencoding()), os.path.normpath(href[1:]))) except: u_print("major problem encountered") return href else: base, fname = os.path.split(url) if DEBUG2: u_print("base path = "+ base) u_print("root_path = "+ root_path) href = os.path.normpath(os.path.join(base, os.path.normpath(href))) if href.startswith(root_path): if DEBUG2: u_print("href starts with rootpath") u_print("href = " + href) return href if DEBUG2: u_print("href does not start with rootpath") u_print("href = " + href) return os.path.normpath(os.path.join(root_path, href[1:]))
def _select_language(self, choice): '''selects the appropriate file for language translation and attempts to set editarea_language to the same value''' translate['init_translation'](choice) u_print(_("language set to: ") , choice) self.editarea_language = choice
def remove_unwanted(tree, page): # partially tested '''Removes unwanted tags and or attributes from a "tree" created by ElementTree from an html page.''' global __dangerous_text # determine if site security level has been set to override # the default try: security_level = config[page.username]['page_security_level'](page.url) except Exception: try: u_print("page.username = "******"page.username is not defined") try: u_print(config[page.username]) except: u_print("config[page.username] is not defined") raise _allowed = allowed_attributes[security_level] #The following will be updated so as to add result from page. page.security_info = { 'level': security_level, 'number removed': 0, 'tags removed' : [], 'attributes removed': [], 'styles removed': [] } # first, removing unwanted tags unwanted = set() tag_count = {} page.security_info['number removed'] = 0 for element in tree.getiterator(): if element.tag not in _allowed: unwanted.add(element.tag) if element.tag in tag_count: tag_count[element.tag] += 1 else: tag_count[element.tag] = 1 page.security_info['number removed'] += 1 for tag in unwanted: for element in tree.getiterator(tag): element.clear() # removes the text element.tag = None # set up so that cleanup will remove it. page.security_info['tags removed'].append([tag, tag_count[tag]]) if DEBUG: u_print("These unwanted tags have been removed:") u_print(unwanted) # next, removing unwanted attributes of allowed tags unwanted = set() count = 0 for tag in _allowed: for element in tree.getiterator(tag): # Filtering for possible dangerous content in "styles..." if tag == "link": if not 'trusted' in security_level: if not is_link_safe(element, page): page.security_info['styles removed'].append( [tag, '', __dangerous_text]) __dangerous_text = '' element.clear() element.tag = None page.security_info['number removed'] += 1 continue if tag == "meta": for attr in list(element.attrib.items()): if (attr[0].lower() == 'http-equiv' and attr[1].lower() != 'content-type'): page.security_info['attributes removed'].append( [tag, attr[0], attr[1]]) del element.attrib[attr[0]] page.security_info['number removed'] += 1 for attr in list(element.attrib.items()): if attr[0].lower() not in _allowed[tag]: if DEBUG: unwanted.add(attr[0]) page.security_info['attributes removed'].append( [tag, attr[0], '']) del element.attrib[attr[0]] page.security_info['number removed'] += 1 elif attr[0].lower() == 'href': testHREF = unquote_plus(attr[1]).replace("\r","").replace("\n","") testHREF = testHREF.replace("\t","").lstrip().lower() if testHREF.startswith("javascript:"): if DEBUG: u_print("removing href = "+ testHREF) page.security_info['attributes removed'].append( [tag, attr[0], attr[1]]) del element.attrib[attr[0]] page.security_info['number removed'] += 1 # Filtering for possible dangerous content in "styles..." elif attr[0].lower() == 'style': if not 'trusted' in security_level: value = attr[1].lower().replace(' ', '').replace('\t', '') for x in dangerous_strings: if x in value: if DEBUG: unwanted.add(value) page.security_info['styles removed'].append( [tag, attr[0], attr[1]]) del element.attrib[attr[0]] page.security_info['number removed'] += 1 # Filtering for possible dangerous content in "styles...", but # skipping over empty <style/> element. if tag == 'style' and element.text is not None: if not 'trusted' in security_level: text = element.text.lower().replace(' ', '').replace('\t', '') for x in dangerous_strings: if x in text: if DEBUG: unwanted.add(text) page.security_info['styles removed'].append( [tag, '', element.text]) element.clear() element.tag = None page.security_info['number removed'] += 1 # making sure that this is an image if tag == "img" and \ not 'trusted' in security_level: _rem = False if 'src' in element.attrib: src = element.attrib["src"] if src in good_images: pass elif src in bad_images: element.clear() element.tag = None # do not repeat the information; same image #_rem = True else: if validate_image(src, page): good_images.add(src) else: bad_images.add(src) element.clear() element.tag = None _rem = True else: element.clear() element.tag = None _rem = True src = 'No src attribute included.' if _rem: page.security_info['number removed'] += 1 page.security_info['attributes removed'].append( ['img', 'src', "could not validate or accept image:" + src]) __cleanup(tree.getroot(), lambda e: e.tag) if DEBUG: u_print("These unwanted attributes have been removed:") u_print(unwanted) return
def _load_settings(self): ''' loads the user settings from a configuration file; uses default values if file specific settings is not found. ''' success = False pickled_path = os.path.join(self.user_dir, settings_path) try: pickled = open(pickled_path, 'rb') success = True except: u_print("No configuration file found.") u_print("user_dir = ", self.user_dir) if success: try: saved = pickle.load(pickled) pickled.close() except EOFError: self._not_loaded = False self._save_settings() return else: # save the file with the default value self._not_loaded = False self._save_settings() return for key in saved: try: val = UserPreferences.__dict__[key] if isinstance(val, property): val.fset(self, saved[key]) else: u_print("*"*50) u_print("Unless Crunchy has just been updated,") u_print("this should not happen.") u_print("saved variable: %s is not a property", key) except: try: val = getattr(self, key) setattr(self, key, saved[key]) self._preferences[key] = saved[key] except: u_print("*"*50) u_print("Unless Crunchy has just been updated,") u_print("this should not happen.") u_print("saved variable: %s is not recognized" % key) self._not_loaded = False return