diff --git a/README.md b/README.md index dc41000..1443d34 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,9 @@ Though a terminal utility, it's possible to add bookmarks to `buku` without touc - [Cmdline options](#cmdline-options) - [Operational notes](#operational-notes) - [GUI integration](#gui-integration) - - [Add bookmarks to buku](#add-bookmarks-to-buku) + - [Add bookmarks from anywhere](#add-bookmarks-from-anywhere) - [Import bookmarks to browser](#import-bookmarks-to-browser) +- [As a library](#as-a-library) - [Examples](#examples) - [Contributions](#contributions) - [Mentions](#mentions) @@ -246,7 +247,7 @@ Shell completion scripts for Bash, Fish and Zsh can be found in respective subdi `buku` can integrate in a GUI environment with simple tweaks. -### Add bookmarks to buku +### Add bookmarks from anywhere With support for piped input, it's possible to add bookmarks to `buku` using keyboard shortcuts on Linux and OS X. CLIPBOARD (plus PRIMARY on Linux) text selections can be added directly this way. The additional utility required is `xsel` (on Linux) or `pbpaste` (on OS X). @@ -301,6 +302,15 @@ To export specific tags, run: $ buku --export path_to_bookmarks.html --tag tag 1, tag 2 Once exported, import the html file in your browser. +## As a library + +`buku` can be used as a powerful bookmark management library. All functionality are available through carefully designed APIs. `main()` is a good usage example. It's also possible to use a custom database file in multi-user scenarios. Check out the documentation for the following APIs which accept an optional argument as database file: + + BukuDb.initdb(dbfile=None) + BukuCrypt.encrypt_file(iterations, dbfile=None) + BukuCrypt.decrypt_file(iterations, dbfile=None) +NOTE: This flexibility is not exposed in the program. + ## Examples 1. **Add** a bookmark with **tags** `linux news` and `open source`, **comment** `Informative website on Linux and open source`, **fetch page title** from the web: diff --git a/buku.py b/buku.py index 7e33594..d4d1af5 100755 --- a/buku.py +++ b/buku.py @@ -55,7 +55,7 @@ http_handler = None # urllib3 PoolManager handler htmlparser = None # Use a single HTML Parser instance # Disguise as Firefox on Ubuntu -USER_AGENT = ('Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:48.0) Gecko/20100101 Firefox/48.0') +USER_AGENT = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:48.0) Gecko/20100101 Firefox/48.0' # Crypto globals BLOCKSIZE = 65536 @@ -136,10 +136,11 @@ class BukuCrypt: return hasher.digest() @staticmethod - def encrypt_file(iterations): + def encrypt_file(iterations, dbfile=None): '''Encrypt the bookmarks database file :param iterations: number of iterations for key generation + :param dbfile: custom database file path (including filename) ''' try: @@ -157,14 +158,20 @@ class BukuCrypt: logger.error('Iterations must be >= 1') sys.exit(1) - dbpath = os.path.join(BukuDb.get_dbdir_path(), 'bookmarks.db') - encpath = '%s.enc' % dbpath - if not os.path.exists(dbpath): - logger.error('%s missing. Already encrypted?', dbpath) - sys.exit(1) + if not dbfile: + dbfile = os.path.join(BukuDb.get_default_dbdir(), 'bookmarks.db') + encfile = '%s.enc' % dbfile - # If both encrypted file and flat file exist, error out - if os.path.exists(dbpath) and os.path.exists(encpath): + db_exists = os.path.exists(dbfile) + enc_exists = os.path.exists(encfile) + + if db_exists and not enc_exists: + pass + elif not db_exists: + logger.error('%s missing. Already encrypted?', dbfile) + sys.exit(1) + else: + # db_exists and enc_exists logger.error('Both encrypted and flat DB files exist!') sys.exit(1) @@ -178,8 +185,12 @@ class BukuCrypt: logger.error('Passwords do not match') sys.exit(1) - # Get SHA256 hash of DB file - dbhash = BukuCrypt.get_filehash(dbpath) + try: + # Get SHA256 hash of DB file + dbhash = BukuCrypt.get_filehash(dbfile) + except Exception as e: + logger.error(e) + sys.exit(1) # Generate random 256-bit salt and key salt = os.urandom(SALT_SIZE) @@ -194,10 +205,10 @@ class BukuCrypt: modes.CBC(iv), backend=default_backend() ).encryptor() - filesize = os.path.getsize(dbpath) + filesize = os.path.getsize(dbfile) - with open(dbpath, 'rb') as infp: - with open(encpath, 'wb') as outfp: + try: + with open(dbfile, 'rb') as infp, open(encfile, 'wb') as outfp: outfp.write(struct.pack('