|
@@ -1,4 +1,4 @@
|
|
|
-#============================================================================
|
|
|
+# ============================================================================
|
|
|
# This file is part of Pwman3.
|
|
|
#
|
|
|
# Pwman3 is free software; you can redistribute iut and/or modify
|
|
@@ -13,12 +13,11 @@
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
# along with Pwman3; if not, write to the Free Software
|
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
-#============================================================================
|
|
|
-# Copyright (C) 2012 Oz Nahum <nahumoz@gmail.com>
|
|
|
-#============================================================================
|
|
|
-#============================================================================
|
|
|
+# ============================================================================
|
|
|
+# Copyright (C) 2012, 2013, 2014 Oz Nahum Tiram <nahumoz@gmail.com>
|
|
|
+# ============================================================================
|
|
|
# Copyright (C) 2006 Ivan Kelly <ivan@ivankelly.net>
|
|
|
-#============================================================================
|
|
|
+# ============================================================================
|
|
|
|
|
|
"""SQLite Database implementation."""
|
|
|
from pwman.data.database import Database, DatabaseException
|
|
@@ -354,3 +353,127 @@ class SQLiteDatabaseNewForm(Database):
|
|
|
return None
|
|
|
else:
|
|
|
return keyrow[0]
|
|
|
+
|
|
|
+
|
|
|
+class SQLite(SQLiteDatabaseNewForm):
|
|
|
+
|
|
|
+ def __init__(self, filename, dbformat=0.6):
|
|
|
+ """Initialise SQLitePwmanDatabase instance."""
|
|
|
+ self._filename = filename
|
|
|
+ self.dbformat = dbformat
|
|
|
+
|
|
|
+ def _open(self):
|
|
|
+ self._con = sqlite.connect(self._filename)
|
|
|
+ self._cur = self._con.cursor()
|
|
|
+
|
|
|
+ def listnodes(self, filter=None):
|
|
|
+ if not filter:
|
|
|
+ sql_all = "SELECT ID FROM NODE"
|
|
|
+ self._cur.execute(sql_all)
|
|
|
+ ids = self._cur.fetchall()
|
|
|
+ return ids
|
|
|
+ else:
|
|
|
+ tagid = self._get_tag(filter)
|
|
|
+ sql_filter = "SELECT NODEID FROM LOOKUP WHERE TAGID = ? "
|
|
|
+ self._cur.execute(sql_filter, tagid)
|
|
|
+ ids = self._cur.fetchall()
|
|
|
+ return ids
|
|
|
+
|
|
|
+ def _create_tables(self):
|
|
|
+ self._cur.execute("PRAGMA TABLE_INFO(NODE)")
|
|
|
+ if self._cur.fetchone() is not None:
|
|
|
+ return
|
|
|
+
|
|
|
+ self._cur.execute("CREATE TABLE NODE (ID INTEGER PRIMARY KEY "
|
|
|
+ "AUTOINCREMENT, "
|
|
|
+ "USER TEXT NOT NULL, "
|
|
|
+ "PASSWORD TEXT NOT NULL, "
|
|
|
+ "URL TEXT NOT NULL,"
|
|
|
+ "NOTES TEXT NOT NULL)")
|
|
|
+
|
|
|
+ self._cur.execute("CREATE TABLE TAG"
|
|
|
+ "(ID INTEGER PRIMARY KEY AUTOINCREMENT,"
|
|
|
+ "DATA BLOB NOT NULL UNIQUE)")
|
|
|
+
|
|
|
+ self._cur.execute("CREATE TABLE LOOKUP ("
|
|
|
+ "nodeid INTEGER NOT NULL, "
|
|
|
+ "tagid INTEGER NOT NULL, "
|
|
|
+ "FOREIGN KEY(nodeid) REFERENCES NODE(ID),"
|
|
|
+ "FOREIGN KEY(tagid) REFERENCES TAG(ID))")
|
|
|
+
|
|
|
+ self._cur.execute("CREATE TABLE CRYPTO"
|
|
|
+ "(SEED TEXT,"
|
|
|
+ " DIGEST TEXT)")
|
|
|
+
|
|
|
+ # create a table to hold DB version info
|
|
|
+ self._cur.execute("CREATE TABLE DBVERSION"
|
|
|
+ "(DB VERSION TEXT NOT NULL DEFAULT '%s')" %
|
|
|
+ self.dbformat)
|
|
|
+ self._cur.execute("INSERT INTO DBVERSION VALUES('%s')" %
|
|
|
+ self.dbformat)
|
|
|
+ try:
|
|
|
+ self._con.commit()
|
|
|
+ except DatabaseException as e: # pragma: no cover
|
|
|
+ self._con.rollback()
|
|
|
+ raise e
|
|
|
+
|
|
|
+ def fetch_crypto_info(self):
|
|
|
+ self._cur.execute("SELECT * FROM CRYPTO")
|
|
|
+ keyrow = self._cur.fetchone()
|
|
|
+ return keyrow
|
|
|
+
|
|
|
+ def save_crypto_info(self, seed, digest):
|
|
|
+ """save the random seed and the digested key"""
|
|
|
+ self._cur.execute("DELETE FROM CRYPTO")
|
|
|
+ self._cur.execute("INSERT INTO CRYPTO VALUES(?, ?)", [seed, digest])
|
|
|
+ self._con.commit()
|
|
|
+
|
|
|
+ def add_node(self, node):
|
|
|
+ sql = ("INSERT INTO NODE(USER, PASSWORD, URL, NOTES)"
|
|
|
+ "VALUES(?, ?, ?, ?)")
|
|
|
+ node_tags = list(node)
|
|
|
+ node, tags = node_tags[:4], node_tags[-1]
|
|
|
+ self._cur.execute(sql, (node))
|
|
|
+ self._setnodetags(self._cur.lastrowid, tags)
|
|
|
+ self._con.commit()
|
|
|
+
|
|
|
+ def _get_tag(self, tagcipher):
|
|
|
+ sql_search = "SELECT ID FROM TAG WHERE DATA LIKE (?)"
|
|
|
+ self._cur.execute(sql_search, ([tagcipher]))
|
|
|
+ rv = self._cur.fetchone()
|
|
|
+ return rv
|
|
|
+
|
|
|
+ def _get_or_create_tag(self, tagcipher):
|
|
|
+ rv = self._get_tag(tagcipher)
|
|
|
+ if rv:
|
|
|
+ return rv[0]
|
|
|
+ else:
|
|
|
+ sql_insert = "INSERT INTO TAG(DATA) VALUES(?)"
|
|
|
+ self._cur.execute(sql_insert, ([tagcipher]))
|
|
|
+ return self._cur.lastrowid
|
|
|
+
|
|
|
+ def _update_tag_lookup(self, nodeid, tid):
|
|
|
+ sql_lookup = "INSERT INTO LOOKUP(nodeid, tagid) VALUES(?,?)"
|
|
|
+ self._cur.execute(sql_lookup, (nodeid, tid))
|
|
|
+
|
|
|
+ def _setnodetags(self, nodeid, tags):
|
|
|
+ for tag in tags:
|
|
|
+ tid = self._get_or_create_tag(tag)
|
|
|
+ self._update_tag_lookup(nodeid, tid)
|
|
|
+
|
|
|
+ def getnodes(self, ids):
|
|
|
+ sql = "SELECT * FROM NODE WHERE ID IN (%s)" % ','.join('?'*len(ids))
|
|
|
+ self._cur.execute(sql, (ids))
|
|
|
+ nodes = self._cur.fetchall()
|
|
|
+ return nodes
|
|
|
+
|
|
|
+ def editnode(self, id, **kwargs):
|
|
|
+ sql = ("UPDATE NODE SET %s WHERE ID = ? "
|
|
|
+ "" % ','.join('%s=?' % k for k in list(kwargs)))
|
|
|
+ self._cur.execute(sql, (list(kwargs.values()) + [id]))
|
|
|
+ self._con.commit()
|
|
|
+ # TODO, update tags lookup
|
|
|
+
|
|
|
+ def close(self):
|
|
|
+ self._cur.close()
|
|
|
+ self._con.close()
|