/** * @author Dirk Bergstrom * * Keyring for webOS - Easy password management on your phone. * Copyright (C) 2009-2010, Dirk Bergstrom, keyring@otisbean.com * * 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 3 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, see <http://www.gnu.org/licenses/>. */ package com.otisbean.keyring.converters; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.Date; import java.util.Hashtable; import java.util.Iterator; import com.otisbean.keyring.Item; import com.otisbean.keyring.Ring; /** * Export CodeWallet Pro export format as Keyring for webOS. * * @author Matt Williams, Dirk Bergstrom */ public class EWalletExportConverter extends Converter { public EWalletExportConverter() { needsInputFilePassword = false; } private Collection<String[]> readInputFile(String inFile) throws Exception { Hashtable<String, String[]> cards = new Hashtable<String, String[]>(); try { Reader fr = getReader(inFile); BufferedReader br = new BufferedReader(fr); String thisline = br.readLine(); String lastline = ""; if (null == thisline) { throw new Exception("Input file is empty!"); } int nameidx = 0; int categoryidx = 1; int accountidx = 2; int passwordidx = 3; int notesidx = 4; int urlidx = 5; // boolean readingName = false; boolean entryStart = false; boolean entryEnd = false; boolean readingNote = false; String[] thisEntry = new String[] { "", "", "", "", "", "" }; String thisCategory = ""; while (thisline != null) { // log(thisline); if (thisline.startsWith("Category: ")) { entryEnd = true; } else if (thisline.length() == 0) { if (readingNote) { thisEntry[notesidx] += thisline + "\n"; } } else { if (!readingNote) { // If we hit the next card, have // to add current card to list and start the new one here. if ((thisline.toLowerCase().startsWith("card name ") || (thisline.toLowerCase().startsWith("card") && !thisline.startsWith("Card Notes") && !thisline.startsWith("Card Number") && !thisline.startsWith("Card Provider"))) && lastline.length() == 0) { if (entryStart) { // Code copied from below for adding card to list thisEntry[categoryidx] = thisCategory; if (cards.containsKey(thisEntry[nameidx])) { log("WARNING: Duplicate entry, skipping: [" + thisEntry[nameidx] + "]"); } else { log("Adding to list: " + thisEntry[nameidx]); cards.put(thisEntry[nameidx], thisEntry); thisEntry = new String[] { "", "", "", "", "", "" }; } // entryStart = false; entryEnd = false; } // Code copied from above for starting new card. entryStart = true; int keystart = 5; if (thisline.startsWith("Card Name ")) { keystart = "Card Name ".length(); } thisEntry[nameidx] = thisline.substring(keystart); } else if (thisline.toLowerCase().startsWith("user name ")) { thisEntry[accountidx] = thisline.substring("User Name ".length()); } else if (thisline.toLowerCase().startsWith("password ")) { thisEntry[passwordidx] = thisline.substring("Password ".length()); } else if (thisline.toLowerCase().startsWith("url ")) { thisEntry[urlidx] = thisline.substring("URL " .length()); } else if (thisline.equals("Card Notes")) { readingNote = true; thisEntry[notesidx] += thisline + "\n"; } else { // Anything else, write to the notes. thisEntry[notesidx] += thisline + "\n"; } } else { // If we are reading a note and hit the next card, have // to add current card to list and start the new one // here. if ((thisline.toLowerCase().startsWith("card name ") || (thisline.toLowerCase().startsWith("card") && !thisline.startsWith("Card Notes") && !thisline.startsWith("Card Number") && !thisline.startsWith("Card Provider"))) && lastline.length() == 0) { readingNote = false; // Code copied from below for adding card to list thisEntry[categoryidx] = thisCategory; if (cards.containsKey(thisEntry[nameidx])) { log("WARNING: Duplicate entry, skipping: [" + thisEntry[nameidx] + "]"); } else { log("Adding to list: " + thisEntry[nameidx]); cards.put(thisEntry[nameidx], thisEntry); thisEntry = new String[] { "", "", "", "", "", "" }; } entryEnd = false; // Code copied from above for starting new card. entryStart = true; int keystart = 5; if (thisline.startsWith("Card Name ")) keystart = "Card Name ".length(); thisEntry[nameidx] = thisline.substring(keystart); } else { thisEntry[notesidx] += thisline + "\n"; } } } if (entryEnd) { if (entryStart) { thisEntry[categoryidx] = thisCategory; if (cards.containsKey(thisEntry[nameidx])) { log("WARNING: Duplicate entry, skipping: [" + thisEntry[nameidx] + "]"); } else { log("Adding to list: " + thisEntry[nameidx]); cards.put(thisEntry[nameidx], thisEntry); thisEntry = new String[] { "", "", "", "", "", "" }; // entries.add(thisEntry); } } entryEnd = false; if (thisline.startsWith("Category: ")) { thisCategory = thisline.substring("Category: ".length()); readingNote = false; entryStart = false; } } lastline = thisline; thisline = br.readLine(); } // (thisline != null) // Add last record if it hasn't been done before we hit EOF if (entryStart && !entryEnd) { thisEntry[categoryidx] = thisCategory; if (cards.containsKey(thisEntry[nameidx])) { log("WARNING: Duplicate entry, skipping: [" + thisEntry[nameidx] + "]"); } else { log("Adding to list: " + thisEntry[nameidx]); cards.put(thisEntry[nameidx], thisEntry); } } br.close(); br = null; fr.close(); fr = null; } catch (Exception ex) { logError("Exception processing input file:" + ex.getMessage()); throw ex; } // return entries; return cards.values(); } @SuppressWarnings("unchecked") @Override public Ring convert(String inFile, String inPassword, String outPassword) throws Exception { Collection<String[]> entries = readInputFile(inFile); Ring ring = new Ring(outPassword); Date now = new Date(); int exported = 0; for (Iterator i = entries.iterator(); i.hasNext();) { String[] entry = (String[]) i.next(); String name = entry[0]; String category = entry[1]; String account = entry[2]; String password = entry[3]; String notes = entry[4]; String url = entry[5]; /* We'll pretend that each item was created when it was imported. */ long changed = now.getTime(); ring.addItem(new Item(ring, account, password, url, notes, name, category, changed, changed, changed)); exported++; } return ring; } private String detectEncoding(InputStream is) { String encoding = System.getProperty("file.encoding"); try { byte[] bytes = new byte[2];// {0,0}; is.read(bytes); if (bytes[0] == 0) encoding = "UTF-16BE"; else if (bytes[1] == 0) encoding = "UTF-16LE"; else if (bytes[0] < 0) encoding = "UTF-16"; } catch (IOException ex) { logError("Error detecting file encoding, using default."); } return encoding; } protected Reader getReader(String infileName) throws FileNotFoundException { try { FileInputStream fis = new FileInputStream(infileName); String encoding = detectEncoding(fis); fis.close(); log("Using " + encoding + " encoding to read input file (" + infileName + ")"); return new InputStreamReader(new FileInputStream(infileName), encoding); } catch (UnsupportedEncodingException ex) { return new FileReader(infileName); } catch (IOException ex) { return new FileReader(infileName); } } }