Преглед изворни кода

release v0.2.1

prepare release of v0.2.1
oz123 пре 12 година
родитељ
комит
c46ba7570a
8 измењених фајлова са 107 додато и 92 уклоњено
  1. 9 1
      ChangeLog
  2. 1 1
      PKG-INFO
  3. 8 7
      pwman/__init__.py
  4. 23 19
      pwman/data/drivers/sqlite.py
  5. 56 52
      pwman/ui/cli.py
  6. 3 7
      pwman/util/crypto.py
  7. 4 5
      scripts/pwman3
  8. 3 0
      setup.py

+ 9 - 1
ChangeLog

@@ -1,4 +1,12 @@
-2012-10-06 Oz Nahumn <nahumoz@gmail.com>
+2012-12-14 Oz Nahum <nahumoz@gmail.com>
+	* Version 0.2.1 
+	* implement open uri function
+	* better MacOSX logic
+	* implement test mode, so code can run locally
+	* use ArgParse 
+	* some improvements on documentation
+
+2012-10-06 Oz Nahum <nahumoz@gmail.com>
 	* added Debian patches.
 	* added Debian patches.
     * Merge pull request from David North.
     * Merge pull request from David North.
 	* Add copy to clipboard on Mac OSX
 	* Add copy to clipboard on Mac OSX

+ 1 - 1
PKG-INFO

@@ -1,7 +1,7 @@
 Metadata-Version: 1.0
 Metadata-Version: 1.0
 Name: Pwman3
 Name: Pwman3
 Summary: Pwman is a password management application.
 Summary: Pwman is a password management application.
-Home-page: https://github.com/oz123/pwman3
+Home-page: https://github.com/pwman3/pwman3
 Author: Oz Nahum
 Author: Oz Nahum
 Author-email: nahumoz@gmail.com
 Author-email: nahumoz@gmail.com
 License: GNU GPL
 License: GNU GPL

+ 8 - 7
pwman/__init__.py

@@ -1,15 +1,15 @@
 #============================================================================
 #============================================================================
 # This file is part of Pwman3.
 # This file is part of Pwman3.
-# 
+#
 # Pwman3 is free software; you can redistribute it and/or modify
 # Pwman3 is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License, version 2
 # it under the terms of the GNU General Public License, version 2
-# as published by the Free Software Foundation; 
-# 
+# as published by the Free Software Foundation;
+#
 # Pwman3 is distributed in the hope that it will be useful,
 # Pwman3 is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # You should have received a copy of the GNU General Public License
 # along with Pwman3; if not, write to the Free Software
 # along with Pwman3; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
@@ -20,10 +20,11 @@
 #============================================================================
 #============================================================================
 
 
 appname = "Pwman3"
 appname = "Pwman3"
-version = "0.1.0"
-website = "http://github.com/oz123/pwman3"
+version = "0.2.1"
+website = "http://github.com/pwman3/pwman3"
 author = "Oz Nahum"
 author = "Oz Nahum"
 authoremail = "nahumoz@gmail.com"
 authoremail = "nahumoz@gmail.com"
-description = "Pwman is a password management application."
+description = "Pwman is a lightweight command line password management\
+application."
 keywords = "password management sqlite crypto"
 keywords = "password management sqlite crypto"
 
 

+ 23 - 19
pwman/data/drivers/sqlite.py

@@ -1,15 +1,15 @@
 #============================================================================
 #============================================================================
 # This file is part of Pwman3.
 # This file is part of Pwman3.
-# 
+#
 # Pwman3 is free software; you can redistribute it and/or modify
 # Pwman3 is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License, version 2
 # it under the terms of the GNU General Public License, version 2
-# as published by the Free Software Foundation; 
-# 
+# as published by the Free Software Foundation;
+#
 # Pwman3 is distributed in the hope that it will be useful,
 # Pwman3 is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # You should have received a copy of the GNU General Public License
 # along with Pwman3; if not, write to the Free Software
 # along with Pwman3; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
@@ -39,7 +39,7 @@ import cPickle
 
 
 class SQLiteDatabase(Database):
 class SQLiteDatabase(Database):
     """SQLite Database implementation"""
     """SQLite Database implementation"""
-    
+
     def __init__(self):
     def __init__(self):
         """Initialise SQLitePwmanDatabase instance."""
         """Initialise SQLitePwmanDatabase instance."""
         Database.__init__(self)
         Database.__init__(self)
@@ -77,7 +77,7 @@ class SQLiteDatabase(Database):
                     sql += " INTERSECT "
                     sql += " INTERSECT "
                 else:
                 else:
                     first = False
                     first = False
-                    
+
                 sql += ("SELECT NODE FROM LOOKUP LEFT JOIN TAGS ON TAG = TAGS.ID "
                 sql += ("SELECT NODE FROM LOOKUP LEFT JOIN TAGS ON TAG = TAGS.ID "
                         + " WHERE TAGS.DATA = ?")
                         + " WHERE TAGS.DATA = ?")
                 params.append(cPickle.dumps(t))
                 params.append(cPickle.dumps(t))
@@ -102,7 +102,7 @@ class SQLiteDatabase(Database):
             return tags
             return tags
         except sqlite.DatabaseError, e:
         except sqlite.DatabaseError, e:
             raise DatabaseException("SQLite: %s" % (e))
             raise DatabaseException("SQLite: %s" % (e))
-        
+
     def getnodes(self, ids):
     def getnodes(self, ids):
         nodes = []
         nodes = []
         for i in ids:
         for i in ids:
@@ -125,7 +125,7 @@ class SQLiteDatabase(Database):
         try:
         try:
             sql = "UPDATE NODES SET DATA = ? WHERE ID = ?";
             sql = "UPDATE NODES SET DATA = ? WHERE ID = ?";
             self._cur.execute(sql, [cPickle.dumps(node), id])
             self._cur.execute(sql, [cPickle.dumps(node), id])
-            
+
         except sqlite.DatabaseError, e:
         except sqlite.DatabaseError, e:
             raise DatabaseException("SQLite: %s" % (e))
             raise DatabaseException("SQLite: %s" % (e))
         self._setnodetags(node)
         self._setnodetags(node)
@@ -147,7 +147,7 @@ class SQLiteDatabase(Database):
 
 
             self._setnodetags(n)
             self._setnodetags(n)
             self._commit()
             self._commit()
-            
+
     def removenodes(self, nodes):
     def removenodes(self, nodes):
         for n in nodes:
         for n in nodes:
             if not isinstance(n, Node): raise DatabaseException(
             if not isinstance(n, Node): raise DatabaseException(
@@ -155,7 +155,7 @@ class SQLiteDatabase(Database):
             try:
             try:
                 sql = "DELETE FROM NODES WHERE ID = ?";
                 sql = "DELETE FROM NODES WHERE ID = ?";
                 self._cur.execute(sql, [n.get_id()])
                 self._cur.execute(sql, [n.get_id()])
-                
+
             except sqlite.DatabaseError, e:
             except sqlite.DatabaseError, e:
                 raise DatabaseException("SQLite: %s" % (e))
                 raise DatabaseException("SQLite: %s" % (e))
             self._deletenodetags(n)
             self._deletenodetags(n)
@@ -206,7 +206,7 @@ class SQLiteDatabase(Database):
             if not isinstance(t, Tag): raise DatabaseException(
             if not isinstance(t, Tag): raise DatabaseException(
                 "Tried to insert foreign object into database [%s]", t)
                 "Tried to insert foreign object into database [%s]", t)
             data = cPickle.dumps(t)
             data = cPickle.dumps(t)
-            
+
             try:
             try:
                 self._cur.execute(sql, [data])
                 self._cur.execute(sql, [data])
                 row = self._cur.fetchone()
                 row = self._cur.fetchone()
@@ -224,19 +224,19 @@ class SQLiteDatabase(Database):
         try:
         try:
             sql = "DELETE FROM LOOKUP WHERE NODE = ?"
             sql = "DELETE FROM LOOKUP WHERE NODE = ?"
             self._cur.execute(sql, [node.get_id()])
             self._cur.execute(sql, [node.get_id()])
-            
+
         except sqlite.DatabaseError, e:
         except sqlite.DatabaseError, e:
             raise DatabaseException("SQLite: %s" % (e))
             raise DatabaseException("SQLite: %s" % (e))
         self._commit()
         self._commit()
-        
+
     def _setnodetags(self, node):
     def _setnodetags(self, node):
         self._deletenodetags(node)
         self._deletenodetags(node)
         ids = self._tagids(node.get_tags())
         ids = self._tagids(node.get_tags())
-        
+
         for i in ids:
         for i in ids:
             sql = "INSERT OR REPLACE INTO LOOKUP VALUES(?, ?)"
             sql = "INSERT OR REPLACE INTO LOOKUP VALUES(?, ?)"
             params = [node.get_id(), i]
             params = [node.get_id(), i]
-            
+
             try:
             try:
                 self._cur.execute(sql, params)
                 self._cur.execute(sql, params)
             except sqlite.DatabaseError, e:
             except sqlite.DatabaseError, e:
@@ -250,7 +250,7 @@ class SQLiteDatabase(Database):
         except sqlite.DatabaseError, e:
         except sqlite.DatabaseError, e:
             raise DatabaseException("SQLite: %s" % (e))
             raise DatabaseException("SQLite: %s" % (e))
         self._commit()
         self._commit()
-        
+
     def _checktables(self):
     def _checktables(self):
         """ Check if the Pwman tables exist """
         """ Check if the Pwman tables exist """
         self._cur.execute("PRAGMA TABLE_INFO(NODES)")
         self._cur.execute("PRAGMA TABLE_INFO(NODES)")
@@ -271,7 +271,7 @@ class SQLiteDatabase(Database):
             self._cur.execute("CREATE TABLE KEY"
             self._cur.execute("CREATE TABLE KEY"
                               + "(THEKEY TEXT NOT NULL DEFAULT '')");
                               + "(THEKEY TEXT NOT NULL DEFAULT '')");
             self._cur.execute("INSERT INTO KEY VALUES('')");
             self._cur.execute("INSERT INTO KEY VALUES('')");
-            
+
             try:
             try:
                 self._con.commit()
                 self._con.commit()
             except DatabaseError, e:
             except DatabaseError, e:
@@ -288,9 +288,13 @@ class SQLiteDatabase(Database):
             self._con.rollback()
             self._con.rollback()
             raise DatabaseException(
             raise DatabaseException(
                 "SQLite: Error saving key [%s]" % (e))
                 "SQLite: Error saving key [%s]" % (e))
-        
-        
+
+
     def loadkey(self):
     def loadkey(self):
+        """
+        fetch the key to database. the key is also stored
+        encrypted.
+        """
         self._cur.execute("SELECT THEKEY FROM KEY");
         self._cur.execute("SELECT THEKEY FROM KEY");
         keyrow = self._cur.fetchone()
         keyrow = self._cur.fetchone()
         if (keyrow[0] == ''):
         if (keyrow[0] == ''):

+ 56 - 52
pwman/ui/cli.py

@@ -1,15 +1,15 @@
 #============================================================================
 #============================================================================
 # This file is part of Pwman3.
 # This file is part of Pwman3.
-# 
+#
 # Pwman3 is free software; you can redistribute it and/or modify
 # Pwman3 is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License, version 2
 # it under the terms of the GNU General Public License, version 2
-# as published by the Free Software Foundation; 
-# 
+# as published by the Free Software Foundation;
+#
 # Pwman3 is distributed in the hope that it will be useful,
 # Pwman3 is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 # GNU General Public License for more details.
-# 
+#
 # You should have received a copy of the GNU General Public License
 # You should have received a copy of the GNU General Public License
 # along with Pwman3; if not, write to the Free Software
 # along with Pwman3; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
@@ -54,7 +54,7 @@ except ImportError, e:
 class CLICallback(Callback):
 class CLICallback(Callback):
     def getinput(self, question):
     def getinput(self, question):
         return raw_input(question)
         return raw_input(question)
-    
+
     def getsecret(self, question):
     def getsecret(self, question):
         return getpass.getpass(question + ":")
         return getpass.getpass(question + ":")
 
 
@@ -79,7 +79,7 @@ class PwmanCli(cmd.Cmd):
         else:
         else:
 #            traceback.print_exc()
 #            traceback.print_exc()
             print "Error: %s " % (exception)
             print "Error: %s " % (exception)
-    
+
     def do_EOF(self, args):
     def do_EOF(self, args):
         return self.do_exit(args)
         return self.do_exit(args)
 
 
@@ -109,10 +109,10 @@ class PwmanCli(cmd.Cmd):
                 ids += range(int(m.group(1)),
                 ids += range(int(m.group(1)),
                              int(m.group(2))+1)
                              int(m.group(2))+1)
         return ids
         return ids
-    
+
     def get_filesystem_path(self, default=""):
     def get_filesystem_path(self, default=""):
         return getinput("Enter filename: ", default)
         return getinput("Enter filename: ", default)
-    
+
     def get_username(self, default=""):
     def get_username(self, default=""):
         return getinput("Username: ", default)
         return getinput("Username: ", default)
 
 
@@ -170,7 +170,7 @@ class PwmanCli(cmd.Cmd):
         for tn in tagstrings:
         for tn in tagstrings:
             tags.append(Tag(tn))
             tags.append(Tag(tn))
         return tags
         return tags
-        
+
     def print_node(self, node):
     def print_node(self, node):
         width = str(_defaultwidth)
         width = str(_defaultwidth)
         print "Node %d." % (node.get_id())
         print "Node %d." % (node.get_id())
@@ -184,7 +184,7 @@ class PwmanCli(cmd.Cmd):
                                     node.get_notes())
                                     node.get_notes())
         print typeset("Tags: ", ANSI.Red),
         print typeset("Tags: ", ANSI.Red),
         for t in node.get_tags():
         for t in node.get_tags():
-            print "%s " % t.get_name(),
+            print "rr %s " % t.get_name(),
         print
         print
 
 
         def heardEnter():
         def heardEnter():
@@ -203,7 +203,7 @@ class PwmanCli(cmd.Cmd):
                 if ret is not None:
                 if ret is not None:
                     return True
                     return True
             return False
             return False
-        
+
         def waituntil_enter(somepredicate,timeout, period=0.25):
         def waituntil_enter(somepredicate,timeout, period=0.25):
             mustend = time.time() + timeout
             mustend = time.time() + timeout
             while time.time() < mustend:
             while time.time() < mustend:
@@ -212,13 +212,13 @@ class PwmanCli(cmd.Cmd):
                     break
                     break
                 time.sleep(period)
                 time.sleep(period)
             self.do_cls('')
             self.do_cls('')
-        
+
         if sys.platform != 'win32':
         if sys.platform != 'win32':
             print "Type Enter to flush screen (autoflash in 5 sec.)"
             print "Type Enter to flush screen (autoflash in 5 sec.)"
             waituntil_enter(heardEnter, 5)
             waituntil_enter(heardEnter, 5)
         else:
         else:
             print "Press any key to flush screen (autoflash in 5 sec.)"
             print "Press any key to flush screen (autoflash in 5 sec.)"
-            waituntil_enter(heardEnterWin, 5) 
+            waituntil_enter(heardEnterWin, 5)
 
 
     def do_tags(self, arg):
     def do_tags(self, arg):
         tags = self._db.listtags()
         tags = self._db.listtags()
@@ -237,7 +237,7 @@ class PwmanCli(cmd.Cmd):
         enc = CryptoEngine.get()
         enc = CryptoEngine.get()
         if not enc.alive():
         if not enc.alive():
             return strings
             return strings
-        
+
         tags = self._db.listtags()
         tags = self._db.listtags()
         for t in tags:
         for t in tags:
             name = t.get_name()
             name = t.get_name()
@@ -325,7 +325,7 @@ class PwmanCli(cmd.Cmd):
     def do_export(self, arg):
     def do_export(self, arg):
         try:
         try:
             nodes = self.get_ids(arg)
             nodes = self.get_ids(arg)
-                
+
             types = exporter.Exporter.types()
             types = exporter.Exporter.types()
             type = select("Select filetype:", types)
             type = select("Select filetype:", types)
             exp = exporter.Exporter.get(type)
             exp = exporter.Exporter.get(type)
@@ -385,7 +385,7 @@ class PwmanCli(cmd.Cmd):
 
 
     def do_rm(self, arg):
     def do_rm(self, arg):
         self.do_delete(arg)
         self.do_delete(arg)
-        
+
     def do_delete(self, arg):
     def do_delete(self, arg):
         ids = self.get_ids(arg)
         ids = self.get_ids(arg)
         try:
         try:
@@ -404,9 +404,9 @@ class PwmanCli(cmd.Cmd):
 
 
     def do_ls(self, args):
     def do_ls(self, args):
         self.do_list(args)
         self.do_list(args)
-        
+
     def do_list(self, args):
     def do_list(self, args):
-        
+
         if len(args.split()) > 0:
         if len(args.split()) > 0:
             self.do_clear('')
             self.do_clear('')
             self.do_filter(args)
             self.do_filter(args)
@@ -447,7 +447,7 @@ class PwmanCli(cmd.Cmd):
                     c = getonechar("Press <Space> for more, or 'Q' to cancel")
                     c = getonechar("Press <Space> for more, or 'Q' to cancel")
                     if c == 'q':
                     if c == 'q':
                         break
                         break
-        
+
         except Exception, e:
         except Exception, e:
             self.error(e)
             self.error(e)
 
 
@@ -457,7 +457,7 @@ class PwmanCli(cmd.Cmd):
             enc.forget()
             enc.forget()
         except Exception,e:
         except Exception,e:
             self.error(e)
             self.error(e)
-            
+
     def do_passwd(self, args):
     def do_passwd(self, args):
         try:
         try:
             self._db.changepassword()
             self._db.changepassword()
@@ -504,7 +504,7 @@ class PwmanCli(cmd.Cmd):
             print "Config saved."
             print "Config saved."
         except Exception, e:
         except Exception, e:
             self.error(e)
             self.error(e)
-    
+
     def do_cls(self,args):
     def do_cls(self,args):
         os.system('clear')
         os.system('clear')
 
 
@@ -518,7 +518,7 @@ class PwmanCli(cmd.Cmd):
                 node = self._db.getnodes(ids)
                 node = self._db.getnodes(ids)
                 text_to_clipboards(node[0].get_password())
                 text_to_clipboards(node[0].get_password())
                 print """copied password for %s@%s clipboard... erasing in 10 sec...""" %\
                 print """copied password for %s@%s clipboard... erasing in 10 sec...""" %\
-                (node[0].get_username(), node[0].get_url()) 
+                (node[0].get_username(), node[0].get_url())
                 time.sleep(10)
                 time.sleep(10)
                 text_to_clipboards("")
                 text_to_clipboards("")
             except Exception, e:
             except Exception, e:
@@ -528,7 +528,7 @@ class PwmanCli(cmd.Cmd):
 
 
     def do_cp(self,args):
     def do_cp(self,args):
         self.do_copy(args)
         self.do_copy(args)
-    
+
     def do_open(self, args):
     def do_open(self, args):
         ids = self.get_ids(args)
         ids = self.get_ids(args)
         if len(ids) > 1:
         if len(ids) > 1:
@@ -548,12 +548,12 @@ class PwmanCli(cmd.Cmd):
     ##
     ##
     def usage(self, string):
     def usage(self, string):
         print "Usage: %s" % (string)
         print "Usage: %s" % (string)
-    
+
     def help_open(self):
     def help_open(self):
         self.usage("open <ID>")
         self.usage("open <ID>")
         print "Launch default browser with 'xdg-open url',\n\
         print "Launch default browser with 'xdg-open url',\n\
 the url must contain http:// or https://."
 the url must contain http:// or https://."
-    
+
     def help_o(self):
     def help_o(self):
         self.help_open()
         self.help_open()
 
 
@@ -570,7 +570,7 @@ the url must contain http:// or https://."
 
 
     def help_ls(self):
     def help_ls(self):
         self.help_list()
         self.help_list()
-        
+
     def help_list(self):
     def help_list(self):
         self.usage("list <tag> ...")
         self.usage("list <tag> ...")
         print "List nodes that match current or specified filter. ls is an alias."
         print "List nodes that match current or specified filter. ls is an alias."
@@ -606,7 +606,7 @@ the url must contain http:// or https://."
         self.usage("edit <ID|tag> ... ")
         self.usage("edit <ID|tag> ... ")
         print "Edits a nodes."
         print "Edits a nodes."
         self._mult_id_help()
         self._mult_id_help()
-    
+
     def help_import(self):
     def help_import(self):
         self.usage("import [filename] ...")
         self.usage("import [filename] ...")
         print "Imports a nodes from a file."
         print "Imports a nodes from a file."
@@ -615,14 +615,14 @@ the url must contain http:// or https://."
         self.usage("export <ID|tag> ... ")
         self.usage("export <ID|tag> ... ")
         print "Exports a list of ids to an external format. If no IDs or tags are specified, then all nodes under the current filter are exported."
         print "Exports a list of ids to an external format. If no IDs or tags are specified, then all nodes under the current filter are exported."
         self._mult_id_help()
         self._mult_id_help()
-        
+
     def help_new(self):
     def help_new(self):
         self.usage("new")
         self.usage("new")
         print "Creates a new node."
         print "Creates a new node."
-    
+
     def help_rm(self):
     def help_rm(self):
         self.help_delete()
         self.help_delete()
-    
+
     def help_print(self):
     def help_print(self):
         self.usage("print <ID|tag> ...")
         self.usage("print <ID|tag> ...")
         print "Displays a node. ",
         print "Displays a node. ",
@@ -630,7 +630,7 @@ the url must contain http:// or https://."
 
 
     def _mult_id_help(self):
     def _mult_id_help(self):
         print "Multiple ids and nodes can be specified, separated by a space. A range of ids can be specified in the format n-N. e.g. '10-20' would specify all nodes having ids from 10 to 20 inclusive. Tags are considered one-by-one. e.g. 'foo 2 bar' would yield to all nodes with tag 'foo', node 2 and all nodes with tag 'bar'."
         print "Multiple ids and nodes can be specified, separated by a space. A range of ids can be specified in the format n-N. e.g. '10-20' would specify all nodes having ids from 10 to 20 inclusive. Tags are considered one-by-one. e.g. 'foo 2 bar' would yield to all nodes with tag 'foo', node 2 and all nodes with tag 'bar'."
-    
+
     def help_exit(self):
     def help_exit(self):
         self.usage("exit")
         self.usage("exit")
         print "Exits the application."
         print "Exits the application."
@@ -642,10 +642,10 @@ the url must contain http:// or https://."
     def help_set(self):
     def help_set(self):
         self.usage("set [configoption] [value]")
         self.usage("set [configoption] [value]")
         print "Sets a configuration option. If no value is specified, the current value for [configoption] is output. If neither [configoption] nor [value] are specified, the whole current configuration is output. [configoption] must be of the format <section>.<option>"
         print "Sets a configuration option. If no value is specified, the current value for [configoption] is output. If neither [configoption] nor [value] are specified, the whole current configuration is output. [configoption] must be of the format <section>.<option>"
-        
+
     def help_ls(self):
     def help_ls(self):
         self.help_list()
         self.help_list()
-    
+
     def help_passwd(self):
     def help_passwd(self):
         self.usage("passwd")
         self.usage("passwd")
         print "Changes the password on the database. "
         print "Changes the password on the database. "
@@ -665,14 +665,18 @@ the url must contain http:// or https://."
     def help_tags(self):
     def help_tags(self):
         self.usage("tags")
         self.usage("tags")
         print "Displays all tags in used in the database."
         print "Displays all tags in used in the database."
-        
+
     def postloop(self):
     def postloop(self):
         try:
         try:
             readline.write_history_file(self._historyfile)
             readline.write_history_file(self._historyfile)
         except Exception, e:
         except Exception, e:
             pass
             pass
-    
+
     def __init__(self, db, hasxsel):
     def __init__(self, db, hasxsel):
+        """
+        initialize CLI interface, set up the DB
+        connecion, see if we have xsel ...
+        """
         cmd.Cmd.__init__(self)
         cmd.Cmd.__init__(self)
         self.intro = "%s %s (c) %s <%s>" % (pwman.appname, pwman.version,
         self.intro = "%s %s (c) %s <%s>" % (pwman.appname, pwman.version,
                                             pwman.author, pwman.authoremail)
                                             pwman.author, pwman.authoremail)
@@ -709,7 +713,7 @@ class PwmanCliMac(PwmanCli):
             node[0].get_password()
             node[0].get_password()
             text_to_mcclipboard(node[0].get_password())
             text_to_mcclipboard(node[0].get_password())
             print """copied password for %s@%s clipboard... erasing in 10 sec...""" %\
             print """copied password for %s@%s clipboard... erasing in 10 sec...""" %\
-            (node[0].get_username(), node[0].get_url()) 
+            (node[0].get_username(), node[0].get_url())
             time.sleep(10)
             time.sleep(10)
             text_to_clipboards("")
             text_to_clipboards("")
         except Exception, e:
         except Exception, e:
@@ -717,7 +721,7 @@ class PwmanCliMac(PwmanCli):
 
 
     def do_cp(self,args):
     def do_cp(self,args):
         self.do_copy(args)
         self.do_copy(args)
-        
+
     def do_open(self, args):
     def do_open(self, args):
         ids = self.get_ids(args)
         ids = self.get_ids(args)
         if len(ids) > 1:
         if len(ids) > 1:
@@ -732,7 +736,7 @@ class PwmanCliMac(PwmanCli):
 
 
     def do_o(self, args):
     def do_o(self, args):
         self.do_open(args)
         self.do_open(args)
-    
+
     ##
     ##
     ## Help functions
     ## Help functions
     ##
     ##
@@ -740,7 +744,7 @@ class PwmanCliMac(PwmanCli):
         self.usage("open <ID>")
         self.usage("open <ID>")
         print "Launch default browser with 'open url',\n\
         print "Launch default browser with 'open url',\n\
 the url must contain http:// or https://."
 the url must contain http:// or https://."
-    
+
     def help_o(self):
     def help_o(self):
         self.help_open()
         self.help_open()
 
 
@@ -757,7 +761,7 @@ def getonechar(question, width=_defaultwidth):
     question = "%s " % (question)
     question = "%s " % (question)
     print question.ljust(width),
     print question.ljust(width),
     sys.stdout.flush()
     sys.stdout.flush()
-        
+
     fd = sys.stdin.fileno()
     fd = sys.stdin.fileno()
     tty_mode = tty.tcgetattr(fd)
     tty_mode = tty.tcgetattr(fd)
     tty.setcbreak(fd)
     tty.setcbreak(fd)
@@ -767,7 +771,7 @@ def getonechar(question, width=_defaultwidth):
         tty.tcsetattr(fd, tty.TCSAFLUSH, tty_mode)
         tty.tcsetattr(fd, tty.TCSAFLUSH, tty_mode)
     print ch
     print ch
     return ch
     return ch
-    
+
 def getyesno(question, defaultyes=False, width=_defaultwidth):
 def getyesno(question, defaultyes=False, width=_defaultwidth):
     if (defaultyes):
     if (defaultyes):
         default = "[Y/n]"
         default = "[Y/n]"
@@ -801,7 +805,7 @@ def getinput(question, default="", completer=None, width=_defaultwidth):
         readline.set_startup_hook(defaulter)
         readline.set_startup_hook(defaulter)
         oldcompleter = readline.get_completer()
         oldcompleter = readline.get_completer()
         readline.set_completer(completer)
         readline.set_completer(completer)
-        
+
         x = raw_input(question.ljust(width))
         x = raw_input(question.ljust(width))
 
 
         readline.set_completer(oldcompleter)
         readline.set_completer(oldcompleter)
@@ -822,8 +826,8 @@ def getpassword(question, width=_defaultwidth, echo=False):
                 return a1
                 return a1
             else:
             else:
                 print "Passwords don't match. Try again."
                 print "Passwords don't match. Try again."
-        
-        
+
+
 def typeset(text, color, bold=False, underline=False):
 def typeset(text, color, bold=False, underline=False):
     if not config.get_value("Global", "colors") == 'yes':
     if not config.get_value("Global", "colors") == 'yes':
         return text
         return text
@@ -858,12 +862,12 @@ def text_to_clipboards(text):
         xsel_proc.communicate(text)
         xsel_proc.communicate(text)
         # "clipboard":
         # "clipboard":
         xsel_proc = sp.Popen(['xsel', '-bi'], stdin=sp.PIPE)
         xsel_proc = sp.Popen(['xsel', '-bi'], stdin=sp.PIPE)
-        xsel_proc.communicate(text) 
+        xsel_proc.communicate(text)
     except OSError, e:
     except OSError, e:
         print e, "\nExecuting xsel failed, is it installed ?\n \
         print e, "\nExecuting xsel failed, is it installed ?\n \
 please check your configuration file ... "
 please check your configuration file ... "
-        
-        
+
+
 def text_to_mcclipboards(text):
 def text_to_mcclipboards(text):
     """
     """
     copy text to mac os x clip board
     copy text to mac os x clip board
@@ -889,12 +893,12 @@ def open_url(link, MacOS=False):
        sp.Popen([uopen, link], stdin=sp.PIPE)
        sp.Popen([uopen, link], stdin=sp.PIPE)
     except OSError, e:
     except OSError, e:
         print "Executing open_url failed with:\n", e
         print "Executing open_url failed with:\n", e
-    
+
 
 
 class CliMenu(object):
 class CliMenu(object):
     def __init__(self):
     def __init__(self):
         self.items = []
         self.items = []
-        
+
     def add(self, item):
     def add(self, item):
         if (isinstance(item, CliMenuItem)):
         if (isinstance(item, CliMenuItem)):
             self.items.append(item)
             self.items.append(item)
@@ -913,21 +917,21 @@ class CliMenu(object):
                         currentstr += ("%s " % (c))
                         currentstr += ("%s " % (c))
                 else:
                 else:
                     currentstr = current
                     currentstr = current
-                    
+
                 print ("%d - %-"+str(_defaultwidth)+"s %s") % (i, x.name+":",
                 print ("%d - %-"+str(_defaultwidth)+"s %s") % (i, x.name+":",
                                                                currentstr)
                                                                currentstr)
             print "%c - Finish editing" % ('X')
             print "%c - Finish editing" % ('X')
             option = getonechar("Enter your choice:")
             option = getonechar("Enter your choice:")
             try:
             try:
                 # substract 1 because array subscripts start at 1
                 # substract 1 because array subscripts start at 1
-                selection = int(option) - 1 
+                selection = int(option) - 1
                 value = self.items[selection].editor(self.items[selection].getter())
                 value = self.items[selection].editor(self.items[selection].getter())
                 self.items[selection].setter(value)
                 self.items[selection].setter(value)
             except (ValueError,IndexError):
             except (ValueError,IndexError):
                 if (option.upper() == 'X'):
                 if (option.upper() == 'X'):
                     break
                     break
                 print "Invalid selection"
                 print "Invalid selection"
-                
+
 class CliMenuItem(object):
 class CliMenuItem(object):
     def __init__(self, name, editor, getter, setter):
     def __init__(self, name, editor, getter, setter):
         self.name = name
         self.name = name

+ 3 - 7
pwman/util/crypto.py

@@ -40,8 +40,8 @@ CryptoEngine.init(params)
 crypto = CryptoEngine.get()
 crypto = CryptoEngine.get()
 ciphertext = crypto.encrypt("plaintext")
 ciphertext = crypto.encrypt("plaintext")
 plaintext = cyypto.decrypt(ciphertext)
 plaintext = cyypto.decrypt(ciphertext)
-
 """
 """
+
 from Crypto.Cipher import Blowfish as cBlowfish
 from Crypto.Cipher import Blowfish as cBlowfish
 from Crypto.Cipher import AES as cAES
 from Crypto.Cipher import AES as cAES
 from Crypto.Cipher import ARC2 as cARC2
 from Crypto.Cipher import ARC2 as cARC2
@@ -104,7 +104,7 @@ class CryptoEngine:
     @classmethod
     @classmethod
     def get(cls):
     def get(cls):
         """
         """
-        get() -> CryptoEngine
+        CryptoEngine.get() -> CryptoEngine
         Return an instance of CryptoEngine.
         Return an instance of CryptoEngine.
         If no instance is found, a CryptoException is raised.
         If no instance is found, a CryptoException is raised.
         """
         """
@@ -169,13 +169,9 @@ class CryptoEngine:
         Decrypt ciphertext and returns the obj that was encrypted.
         Decrypt ciphertext and returns the obj that was encrypted.
         If key is bad, a CryptoBadKeyException is raised
         If key is bad, a CryptoBadKeyException is raised
         Can also raise a CryptoException and CryptoUnsupportedException"""
         Can also raise a CryptoException and CryptoUnsupportedException"""
-        print ciphertext
         cipher = self._getcipher()
         cipher = self._getcipher()
         ciphertext = str(ciphertext).decode('base64')
         ciphertext = str(ciphertext).decode('base64')
         plaintext = cipher.decrypt(ciphertext)
         plaintext = cipher.decrypt(ciphertext)
-        print plaintext
-        #import pdb
-        #pdb.set_trace()
         return self._retrievedata(plaintext)
         return self._retrievedata(plaintext)
 
 
     def set_cryptedkey(self, key):
     def set_cryptedkey(self, key):
@@ -277,7 +273,7 @@ password again")
 
 
         while tries < max_tries:
         while tries < max_tries:
             try:
             try:
-                password = self._callback.getsecret("Please enter your\
+                password = self._callback.getsecret("Please enter your \
 password")
 password")
                 tmpcipher = self._getcipher_real(password, self._algo)
                 tmpcipher = self._getcipher_real(password, self._algo)
                 plainkey = tmpcipher.decrypt(str(self._keycrypted).decode(
                 plainkey = tmpcipher.decrypt(str(self._keycrypted).decode(

+ 4 - 5
scripts/pwman3

@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 #============================================================================
 #============================================================================
 # This file is part of Pwman3.
 # This file is part of Pwman3.
 #
 #
@@ -15,7 +15,6 @@
 # along with Pwman3; if not, write to the Free Software
 # along with Pwman3; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #============================================================================
 #============================================================================
-#============================================================================
 # Copyright (C) 2012 Oz Nahum <nahumoz@gmail.com>
 # Copyright (C) 2012 Oz Nahum <nahumoz@gmail.com>
 #============================================================================
 #============================================================================
 # Copyright (C) 2006 Ivan Kelly <ivan@ivankelly.net>
 # Copyright (C) 2006 Ivan Kelly <ivan@ivankelly.net>
@@ -31,7 +30,7 @@ import argparse
 
 
 parser = argparse.ArgumentParser(description='pwman3 - a command line password'\
 parser = argparse.ArgumentParser(description='pwman3 - a command line password'\
 +'manager.')
 +'manager.')
-parser.add_argument('-c','--config', dest='cfile', 
+parser.add_argument('-c','--config', dest='cfile',
                     default=os.path.expanduser("~/.pwman/config"),
                     default=os.path.expanduser("~/.pwman/config"),
                     help='cofiguretion file to read')
                     help='cofiguretion file to read')
 parser.add_argument('-d', '--database', dest='dbase',
 parser.add_argument('-d', '--database', dest='dbase',
@@ -101,7 +100,7 @@ try:
     elif OSX:
     elif OSX:
         pbcopypath = which("pbcopy")
         pbcopypath = which("pbcopy")
         config.set_value("Global", "xsel", pbcopypath)
         config.set_value("Global", "xsel", pbcopypath)
-        
+
     if args.dbase !=  config.get_value('Database', "filename"):
     if args.dbase !=  config.get_value('Database', "filename"):
         config.set_value("Database", "filename", args.dbase)
         config.set_value("Database", "filename", args.dbase)
         _saveconfig = False
         _saveconfig = False
@@ -112,7 +111,7 @@ try:
     # set umask before creating/opening any files
     # set umask before creating/opening any files
     umask = int(config.get_value("Global", "umask"))
     umask = int(config.get_value("Global", "umask"))
     os.umask(umask)
     os.umask(umask)
-    
+
     enc = CryptoEngine.get()
     enc = CryptoEngine.get()
 
 
     dbtype = config.get_value("Database", "type")
     dbtype = config.get_value("Database", "type")

+ 3 - 0
setup.py

@@ -1,4 +1,7 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
+"""
+script to install pwman3
+"""
 
 
 from distutils.core import setup
 from distutils.core import setup
 import pwman
 import pwman