As suggested, patch for importing Palm SplashID CSV files is attached.

Changes/suggestions welcome, feel free to let me know if there's
anything I should change and resubmit.

Will start looking into the new file format in the coming days.

Cheers,

Devan

On 12/4/06, Devan Goodwin <[EMAIL PROTECTED]> wrote:
Hi Erik, thanks for the great response,

On 12/3/06, Erik Grinaker <[EMAIL PROTECTED]> wrote:
> Hi Devan!
>
> On Mon, 2006-11-20 at 21:16 -0400, Devan Goodwin wrote:
> > I'm looking to migrate to Revelation and write an importer for my
> > previous password solution (Palm SplashID).
>
> Cool :) If you don't mind, I'd like to initially include a version of
> your data handler which won't require file format changes. The other
> data handler do this by cramming the data into Revelations existing
> fields, like putting notes into the description field etc.

Good idea. I've been slowly working on the features I mentioned since
I first wrote, but I like the idea of putting that on hold and
reverting to the current code base to implement a quick SplashID CSV
parser. I will submit this first.

>
>
> > I notice a couple things
> > missing or that I would like to have in place before attempting that
> > import, most if not all of which seem to be on the TODO list.
> >
> > 1. Notes stored on entries.
> > 2. Configurable entry types.
>
> Yes - I've actually started spec'ing a new file format which allows for
> this. You can read a draft of it here:
>
> http://oss.codepoet.no/revelation/revelation-file-spec/xhtml/
>
> It's pretty rough, and everything in it is subject to change. Also, the
> encryption section is somewhat outdated, as I'll most likely be using
> LUKS as a crypto backend.
>
>
> > The following are my proposals for behavior and a variety of
> > questions. Feedback would be greatly appreciated.
> >
> > * Entry types stored in a separate XML file in ~/.revelation/.
> > Considered storing the types encrypted in the actual safe, but it
> > seems to me like the kind of thing you might want to share across
> > safes. Perhaps I could store it in the safe and allow just a type
> > export/import feature.
>
> Yeah, I agree - the custom account types should probably be stored as
> configuration data (ie, in ~/.revelation/) and not in the safe, but we
> might consider merging these with account types found in the current
> safe. This needs some careful thought.

Just to clarify the problem you're referring to here, the situation
where a user starts the application and has no custom defined account
types, so the application loads the default types and stores them as
XML in ~/.revelation. User can now modify them as they see fit. User
attempts to open an old safe, we detect this and transparently convert
their entries to the new file format and autosave. I suspect you're
worried about a situation where the user has modified the default
types and the migration can no longer take place?

>
> > * If no type information is found or we're creating a new safe, the
> > default types will be created matching the ones that exist now.
>
> There's alot of room for improvements in the default types, I've listed
> some suggestions in the spec draft but these are likely to change.
>
>
> > * Add assumption that an entry points to a type and contains an
> > independent list of strings corresponding to it's fields. Something
> > like:
> >
> > <entryType>
> >  <id>someid</id>
> >  <name>Friendly Name</name>
> >  <icon>icon</icon>
> >  <openicon>openicon</openicon>
> >  <fields>
> >    <field>
> >      <name>Username</name>
> >      <type>StringField</type>
> >    </field>
> >  </fields>
> > </entryType>
> >
> > <entry>
> >  <type>someid</type>
> >  <fields>
> >    <field>myloginname</field>
> >  </fields>
> > </entry>
> >
> > So basically, a field on an entry is just a string, a field on an
> > entry type carries all the information about how to display it, and we
> > combine the two in the UI.  I think this would be most useful for
> > converting from one type to another. Entries with more fields than
> > their type actually defines would just be displayed differently in the
> > UI. (i.e. 'Unknown field: val')
>
> I think the format defined in the spec draft solves this better, but
> feel free to suggest improvements (radical or not).


Agreed, your spec looks much more well thought out. I haven't gone
through it completely, but I'll start thinking about it heavily and
hopefully start implementing. (one question I did have was the purpose
of both Typename and Datatype)

>
> > * Detect an old save file (i.e. the current format) and prompt to
> > upgrade when the Revelation is started.
>
> I think we should just do this silently.
>

Sounds good. Might have to prompt for user interaction in the case of
the problem I referred to above (assuming I have the right problem in
mind), but otherwise transparent sounds great.

> > I guess that's it so far, I've just begun reading the code so I'm sure
> > more questions will arise, but I was wondering if the above changes
> > sound reasonable and if there's any interest in a patch for such
> > functionality.
>
> If you're volunteering to implement a new file format, then by all
> means, patches are most welcome :) However, it needs to be carefully
> spec'ed first - I want this format to be usable for a long time without
> any changes.
>
> --
> Erik Grinaker <[EMAIL PROTECTED]>
> http://erikg.codepoet.no/
>
> "We act as though comfort and luxury were the chief requirements of
> life, when all that we need to make us happy is something to be
> enthusiastic about."
>                                                   -- Albert Einstein
>

I am indeed volunteering. :) I'll be happy to work with you and any
other developers involved to make sure it meets your standards. I've
been coding in a private repository for a little while now, I have
some readjusting to do in light of the information you provided in
this email. Thanks for the great response, and kudos on a very useful
application.

Cheers,

Devan





--
Devan Goodwin <[EMAIL PROTECTED]>
http://dgoodwin.dangerouslyinc.com



--
Devan Goodwin <[EMAIL PROTECTED]>
http://dgoodwin.dangerouslyinc.com
diff --git a/src/lib/datahandler/Makefile.am b/src/lib/datahandler/Makefile.am
index 2b7edcb..5423171 100644
--- a/src/lib/datahandler/Makefile.am
+++ b/src/lib/datahandler/Makefile.am
@@ -14,6 +14,7 @@ datahandler_PYTHON	= \
 	netrc.py \
 	pwsafe.py \
 	rvl.py \
+	splashid.py \
 	text.py \
 	xhtml.py
 
diff --git a/src/lib/datahandler/__init__.py b/src/lib/datahandler/__init__.py
index 4556070..6236ccc 100644
--- a/src/lib/datahandler/__init__.py
+++ b/src/lib/datahandler/__init__.py
@@ -25,6 +25,7 @@ #
 
 from base import Error, DataError, FormatError, PasswordError, VersionError
 
+from splashid import SplashIdCsv
 from fpm import FPM
 from gpass import GPass04, GPass05
 from netrc import NetRC
@@ -34,6 +35,7 @@ from text import PlainText
 from xhtml import XHTML
 
 HANDLERS = [
+	SplashIdCsv,
 	FPM,
 	GPass04,
 	GPass05,
@@ -79,7 +81,7 @@ def get_export_handlers():
 
 
 def get_import_handlers():
-	"Returns a list of handlers which can import"	
+	"Returns a list of handlers which can import"
 
 	handlers = []
 
diff --git a/src/lib/datahandler/splashid.py b/src/lib/datahandler/splashid.py
new file mode 100644
index 0000000..60ce771
--- /dev/null
+++ b/src/lib/datahandler/splashid.py
@@ -0,0 +1,124 @@
+#
+# Revelation 0.4.7 - a password manager for GNOME 2
+# http://oss.codepoet.no/revelation/
+# $Id$
+#
+# Module for importing data from CSV files.
+#
+# Copyright (c) 2006 Devan Goodwin <[EMAIL PROTECTED]>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+
+import base
+import csv
+import time
+from revelation import data, entry
+
+class SplashIdCsv(base.DataHandler):
+	"""
+	Data handler for CSV files generated by SplashID.
+
+	While SplashID CSV files were used as the basis for this parser,
+	by arranging data in the format similar to what SplashID generates
+	(i.e. use a spreadsheet and export a CSV with the proper format)
+	one should be able to import any CSV file.
+
+	SplashID's CSV data looks like the following:
+
+	Type,Field 1,Field 2,Field 3,Field 4,Field 5,Field 6,Notes,Category
+
+	The mapping to a Revelation generic entry takes place as follows:
+
+	Type: 		Ignored
+	Field 1:	Name
+	Field 2:	Username
+	Field 3:	Password
+	Field 4:	Hostname
+	Field 5:	Added to Description
+	Field 6:	Added to Description
+	Notes:		Added to Description
+	Category:	Folder
+	"""
+
+	name = "SplashID CSV"
+	importer = True
+	exporter = False
+	encryption = False
+
+	def import_data(self, input, password):
+		""" Import data from a file into the entry store. """
+
+		# Replace any vertical tabs with spaces, SplashID seems to use
+		# these to seperate lines within a Notes field:
+		if input.count('\x0b'):
+			input = input.replace('\x0b', ' ')
+
+		entrystore = data.EntryStore()
+
+		# Maintain a hash of folder names to folder entries so we
+		# can use each category encountered to create a new folder
+		# by that name, or use an existing one if we've already
+		# created it:
+		folders = {}
+
+		for line in input.splitlines():
+			for row in csv.reader([line]):
+
+				if len(row) == 9:
+
+					e = entry.GenericEntry()
+					parent = None
+					e.name = row[1]
+					if row[2] != '':
+						e[entry.UsernameField] = row[2]
+					if row[3] != '':
+						e[entry.PasswordField] = row[3]
+					if row[4] != '':
+						e[entry.HostnameField] = row[4]
+
+					# Stuff remaining fields 5 & 6 as well
+					# as notes into the description:
+					description = ''
+					if row[5] != '':
+						description += row[5]
+					if row[6] != '':
+						if len(description) > 0:
+							description += ' / '
+						description += row[6]
+					# Notes:
+					if row[7] != '':
+						if len(description) > 0:
+							description += ' / '
+						description += row[7]
+					if description != '':
+						e.description = description
+
+					# Create and/or add to folder based on
+					# category:
+					category = row[8]
+					if not folders.has_key(category):
+						new_folder = entry.FolderEntry()
+						new_folder.name = category
+						parent = entrystore.add_entry(new_folder)
+						folders[category] = parent
+					else:
+						parent = folders[category]
+
+					e.updated = time.time()
+
+					entrystore.add_entry(e, parent)
+
+		return entrystore

Reply via email to