]> git.phdru.name Git - bookmarks_db.git/blobdiff - bkmk_objects.py
Fix(Robot): Stop splitting and un-splitting URLs
[bookmarks_db.git] / bkmk_objects.py
index cb6530369fa8c20d03619875dc08162933825766..bf5904b3287d2872dd6e871398751bc3118c6700 100644 (file)
-"""
-   Objects to represent bookmarks.html structure
-
-   Written by Oleg BroytMann. Copyright (C) 2000-2007 PhiloSoft Design.
-"""
-
-import os, cgi
-BKMK_FORMAT = os.environ.get("BKMK_FORMAT", "MOZILLA")
-
-
-class Folder(list):
-   isFolder = 1
-   isBookmark = 0
-
-   def __init__(self, add_date=None, comment='', last_modified=None):
-      super(Folder, self).__init__()
-      self.comment = comment
-      self.add_date = add_date
-      self.last_modified = last_modified
-
-   def walk_depth(self, walker, level=0):
-      if hasattr(self, "header"): # root folder
-         prune = 0
-         walker.root_folder(self)
-      else:
-         prune = walker.prune_folder(self)
-         if not prune:
-            walker.start_folder(self, level)
+"""Objects to represent bookmarks.html structure
 
-      if not prune:
-         for object in self:
-            if object.isFolder:
-               object.walk_depth(walker, level+1)
-            elif object.isBookmark:
-               walker.bookmark(object, level)
-            else:
-               walker.ruler(object, level)
-
-         walker.end_folder(self, level)
-
-
-class Bookmark:
-   isFolder = 0
-   isBookmark = 1
-
-   def __init__(self, href, add_date, last_visit=None, last_modified=None,
-         keyword=None, comment='', icon=None, charset=None):
-      self.href = href
-      self.add_date = add_date
-      self.last_visit = last_visit
-      self.last_modified = last_modified
-      self.keyword = keyword
-      self.comment = comment
-      self.icon = icon
-      self.charset = charset
-
-
-class Ruler:
-   isFolder = 0
-   isBookmark = 0
+This file is a part of Bookmarks database and Internet robot.
 
+"""
 
-class Walker:
-   """
-      Interface class. Any instance that will be passed to Folder.walk_depth
-      may be derived from this class. It is not mandatory - unlike Java
-      Python does not require interface classes; but it is convenient to have
-      some methods predefined to no-op, in case you do not want to
-      provide end_folder etc.
-   """
+__author__ = "Oleg Broytman <phd@phdru.name>"
+__copyright__ = "Copyright (C) 2000-2024 PhiloSoft Design"
+__license__ = "GNU GPL"
 
-   def root_folder(self, r):
-      pass
+__all__ = ['Folder', 'Bookmark', 'Ruler', 'Walker', 'Writer', 'Robot',
+           'InverseLinker', 'Linear', 'make_linear', 'make_tree', 'break_tree',
+           'quote_title', 'unquote_title', 'parse_params', 'set_params',
+           ]
 
-   def start_folder(self, f, level):
-      pass
 
-   def end_folder(self, f, level):
-      pass
+from urllib.parse import unquote
+import os
 
-   def bookmark(self, b, level):
-      pass
+BKMK_FORMAT = os.environ.get("BKMK_FORMAT", "MOZILLA")
 
-   def ruler(self, r, level):
-      pass
 
-   def prune_folder(self, folder):
-      return 0
+class Folder(list):
+    isFolder = 1
+    isBookmark = 0
+
+    def __init__(self, add_date=None, comment='', last_modified=None):
+        super(Folder, self).__init__()
+        self.comment = comment
+        self.add_date = add_date
+        self.last_modified = last_modified
+
+    def walk_depth(self, walker, level=0):
+        if hasattr(self, "header"):  # root folder
+            prune = 0
+            walker.root_folder(self)
+        else:
+            prune = walker.prune_folder(self)
+            if not prune:
+                walker.start_folder(self, level)
+
+        if not prune:
+            for object in self:
+                if object.isFolder:
+                    object.walk_depth(walker, level+1)
+                elif object.isBookmark:
+                    walker.bookmark(object, level)
+                else:
+                    walker.ruler(object, level)
+
+            walker.end_folder(self, level)
+
+
+class Bookmark(object):
+    isFolder = 0
+    isBookmark = 1
+
+    def __init__(self, href, add_date, last_visit=None, last_modified=None,
+                 keyword=None, comment='', icon_href=None, icon=None,
+                 charset=None, parser_charset=None):
+        self.href = href
+        self.add_date = add_date
+        self.last_visit = last_visit
+        self.last_modified = last_modified
+        self.keyword = keyword
+        self.comment = comment
+        self.icon_href = icon_href
+        self.icon = icon
+        self.charset = charset
+
+
+class Ruler(object):
+    isFolder = 0
+    isBookmark = 0
+
+
+class Walker(object):
+    """
+       Interface class. Any instance that will be passed to Folder.walk_depth
+       may be derived from this class. It is not mandatory - unlike Java
+       Python does not require interface classes; but it is convenient to have
+       some methods predefined to no-op, in case you do not want to
+       provide end_folder etc.
+    """
+
+    def root_folder(self, r):
+        pass
+
+    def start_folder(self, f, level):
+        pass
+
+    def end_folder(self, f, level):
+        pass
+
+    def bookmark(self, b, level):
+        pass
+
+    def ruler(self, r, level):
+        pass
+
+    def prune_folder(self, folder):
+        return 0
 
 
 class Writer(Walker):
-   def __init__(self, outfile, prune=None):
-      self.outfile = outfile
-      self.prune = prune
+    def __init__(self, outfile, prune=None):
+        self.outfile = outfile
+        self.prune = prune
 
-   def prune_folder(self, folder):
-      return self.prune == folder.name
+    def prune_folder(self, folder):
+        return self.prune == folder.name
 
 
-class Robot:
-   def __init__(self, tempfname, log):
-      self.tempfname = tempfname
-      self.log = log
+class Robot(object):
+    def __init__(self, log):
+        self.log = log
 
-   def stop(self):
-      pass # Nothing to do on cleanup
+    def stop(self):
+        pass  # Nothing to do on cleanup
 
 
 # Helper class to make inverese links (nodes linked to their parent)
 class InverseLinker(Walker):
-   def root_folder(self, r):
-      self.parent_stack = [r]
+    def root_folder(self, r):
+        self.parent_stack = [r]
 
-   def start_folder(self, f, level):
-      f.parent = self.parent_stack[-1]
-      self.parent_stack.append(f) # Push the folder onto the stack of parents
+    def start_folder(self, f, level):
+        f.parent = self.parent_stack[-1]
+        # Push the folder onto the stack of parents
+        self.parent_stack.append(f)
 
-   def end_folder(self, f, level):
-      del self.parent_stack[-1]   # Pop off the stack
+    def end_folder(self, f, level):
+        del self.parent_stack[-1]   # Pop off the stack
 
-   def bookmark(self, b, level):
-      b.parent = self.parent_stack[-1]
+    def bookmark(self, b, level):
+        b.parent = self.parent_stack[-1]
 
-   def ruler(self, r, level):
-      r.parent = self.parent_stack[-1]
+    def ruler(self, r, level):
+        r.parent = self.parent_stack[-1]
 
 
 # Helper class to make linear represenatation of the tree
 class Linear(Walker):
-   def root_folder(self, r):
-      r.linear = [r]
-      self.linear = r.linear
+    def root_folder(self, r):
+        r.linear = [r]
+        self.linear = r.linear
 
-   def add_object(self, object):
-      self.linear.append(object)
+    def add_object(self, object):
+        self.linear.append(object)
 
-   def start_folder(self, f, level):
-      self.add_object(f)
+    def start_folder(self, f, level):
+        self.add_object(f)
 
-   def bookmark(self, b, level):
-      self.add_object(b)
+    def bookmark(self, b, level):
+        self.add_object(b)
 
-   def ruler(self, r, level):
-      self.add_object(r)
+    def ruler(self, r, level):
+        self.add_object(r)
 
 
-# Helper - make linked linear represenatation of the tree, suitable to be stored in sequential storage
+# Helper - make linked linear represenatation of the tree,
+# suitable to be stored in sequential storage.
 def make_linear(root_folder):
-   linker = InverseLinker()
-   root_folder.walk_depth(linker)
+    linker = InverseLinker()
+    root_folder.walk_depth(linker)
 
-   linear = Linear()
-   root_folder.walk_depth(linear)
+    linear = Linear()
+    root_folder.walk_depth(linear)
 
 
-# Helper, opposite of make_linear - make a tree from the linked linear representation
+# Helper, opposite of make_linear -
+# make a tree from the linked linear representation.
 def make_tree(linear):
-   root_folder = linear[0]
-   del linear[0]
+    root_folder = linear[0]
+    del linear[0]
+
+    for object in linear:
+        object.parent.append(object)
 
-   for object in linear:
-      object.parent.append(object)
+    return root_folder
 
-   return root_folder
 
 def break_tree(linear):
-   del linear[0]
+    del linear[0]
 
-   for object in linear:
-      del object.parent
+    for object in linear:
+        del object.parent
 
 
 def quote_title(title):
-   if BKMK_FORMAT == "MOZILLA":
-      #title = cgi.escape(title, 1).replace("'", "&#39;")
-      title = title.replace("'", "&#39;")
-   return title
+    if BKMK_FORMAT == "MOZILLA":
+        title = title.replace("'", "&#39;")
+    return title
+
+
+def unquote_title(title):
+    if BKMK_FORMAT == "MOZILLA":
+        try:
+            from HTMLParser import HTMLParser
+        except ImportError:
+            from html import unescape
+        else:
+            unescape = HTMLParser().unescape
+        title = unescape(
+            title.replace("&amp;", '&'))
+        title = title.replace("&#39;", "'")
+    return title
+
+
+def parse_params(param_str):
+    params = param_str.split(':')
+    main_param = params.pop(0)
+    param_list = {}
+    for param in params:
+        key, value = param.split('=', 1)
+        param_list[key] = unquote(value)
+    return main_param, param_list
+
+
+def set_params(obj, params):
+    if hasattr(params, "items"):
+        params = params.items()
+    for key, value in params:
+        setattr(obj, key, value)