Skip to content

Commit

Permalink
added rdf export
Browse files Browse the repository at this point in the history
  • Loading branch information
Zak Kriner committed Nov 19, 2011
1 parent dfb56ec commit 1a1a86a
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 97 deletions.
21 changes: 21 additions & 0 deletions css/options.css
Expand Up @@ -75,6 +75,10 @@ h2 {
margin-top: 20px;
}

#showExport {
margin-top: 20px;
}

#list h2 {
padding-top: 0px;
margin-top: 0px;
Expand Down Expand Up @@ -104,11 +108,23 @@ h2 {
padding-left: 2px;
}

#export_settings {
padding: 5px;
width: 505px;
float: right;
display: none;
}

#importText {
width: 505px;
height: 150px;
}

#exportText {
width: 505px;
height: 150px;
}

#profile_setting h2 {
padding-top: 0px;
margin-top: 0px;
Expand All @@ -133,6 +149,11 @@ h2 {
text-align: right;
}

#export_buttons {
width: 505px;
text-align: right;
}

.row {
margin-bottom: 5px;
}
Expand Down
41 changes: 38 additions & 3 deletions html/options.html
Expand Up @@ -32,6 +32,9 @@ <h2>Profiles</h2>
<div id="showImport">
<a href="#" onClick="showImport();" class="awesome button">Import Profiles</a>
</div>
<div id="showExport">
<a href="#" onClick="showExport();" class="awesome button">Export Profiles</a>
</div>
<div id="showSettings">
<a href="#" onClick="showOptions();" class="awesome button">General Options</a>
</div>
Expand Down Expand Up @@ -178,11 +181,16 @@ <h2>Profiles</h2>

<div id="import_settings">
<div id="form">
<h2>Import Firefox Profiles</h2>
<h2>Import Profiles</h2>
<div class="row">
<p class="import_help">
<em>
In Firefox PasswordMaker go to <a
Paste export into the box below then click "Import".
</em>
</p>
<p class="import_help">
<em>
Import from Firefox PasswordMaker by going to <a
href="http://passwordmaker.org/Firefox/Mozilla/SeaMonkey/Flock/Netscape/Advanced">Advanced Options</a> &rarr; File &rarr; Export Settings.
Choose RDF as the export type. Edit the .rdf file
in a plain text editor (e.g. notepad) then select
Expand All @@ -192,7 +200,34 @@ <h2>Import Firefox Profiles</h2>
<textarea id="importText"></textarea>
</div>
<div id="import_buttons">
<a href="#" onClick="importRdf();" class="awesome button">Import RDF</a>
<a href="#" onClick="importRdf();" class="awesome button">Import</a>
</div>
</div>
</div>

<div id="export_settings">
<div id="form">
<h2>Export Profiles</h2>
<div class="row">
<p class="export_help">
<em>
Copy and paste into "Import Profiles" section of Chrome PasswordMaker Pro.
</em>
</p>
<p class="export_help">
<em>
To import profiles into Firefox PasswordMaker save
the text below into a plain text document (e.g.
open notepad, paste, save as "profiles.rdf") then
go to
<a
href="http://passwordmaker.org/Firefox/Mozilla/SeaMonkey/Flock/Netscape/Advanced">Advanced Options</a> &rarr; File &rarr; Import Settings.
</em>
</p>
<textarea id="exportText"></textarea>
</div>
<div id="export_buttons">
<a href="#" onClick="copyRdfExport();" class="awesome button">Copy</a>
</div>
</div>
</div>
Expand Down
249 changes: 167 additions & 82 deletions javascript/import.js
Expand Up @@ -2,96 +2,96 @@ function strToBool(v) {
return v.toString() === 'true';
}

// rename 'store-on-disk' -> 'disk' or vice versa
function renameStoreLocation(key){
return renameImportMap(key, RdfImporter.storeLocations);
}

// rename 'md5-v0.6' -> 'md5_v6' or vice versa
function renameHashAlgorithm(key){
return renameImportMap(key, RdfImporter.hashAlgorithms);
}

function renameImportMap(key, list) {
var map = {};
for(var i=0;i<list.length;i++){
map[list[i][0]] = list[i][1];
map[list[i][1]] = list[i][0];
}
return map[key] || key;
}

var RdfImporter = {
attrMap: {
about: {
name: 'rdf_about',
},

// Settings
// TODO? master password
maskmasterpassword: {
name: 'hideMasterPassword',
convert: strToBool,
},
masterpasswordstorage: {
name: 'storeLocation',
convert: function (v) {
return {'store-on-disk': 'disk', 'store-in-memory': 'memory'}[v];
},
},

// Profiles
name: {
name: 'title',
},
whereleetlb: {
name: 'whereToUseL33t',
},
leetlevellb: {
name: 'l33tLevel',
convert: parseInt,
},
hashalgorithmlb: {
name: 'hashAlgorithm',
convert: function (v) {
// rest of the names are the same
return {'hmac-sha256-fixed': 'hmac-sha256_fix',
'md5-v0.6': 'md5_v6',
'hmac-md5-v0.6': 'hmac-md5_v6'}[v] || v;
},
},
passwordlength: {
name: 'passwordLength',
convert: parseInt,
},
usernametb: {
name: 'username',
},
counter: {
name: 'modifier',
},
charset: {
name: 'selectedCharset',
},
prefix: {
name: 'passwordPrefix',
},
suffix: {
name: 'passwordSuffix',
},
protocolcb: {
name: 'url_protocol',
convert: strToBool,
},
subdomaincb: {
name: 'url_subdomain',
convert: strToBool,
},
domaincb: {
name: 'url_domain',
convert: strToBool,
},
pathcb: {
name: 'url_path',
convert: strToBool,
},
// [FF, Chrome]
storeLocations: [
['store-on-disk', 'disk'],
['store-in-memory', 'memory']
],

// [FF, Chrome]
hashAlgorithms: [
['hmac-sha256-fixed', 'hmac-sha256_fix'],
['md5-v0.6', 'md5_v6'],
['hmac-md5-v0.6', 'hmac-md5_v6']
],

// [Group, FF, Chrome, import conversion function, export conversion function]
attrs: [
['all', 'about', 'rdf_about'],
['setting', 'maskMasterPassword', 'hideMasterPassword', strToBool],
['setting', 'masterPasswordStorage', 'storeLocation', renameStoreLocation, renameStoreLocation],
['profile', 'name', 'title'],
['profile', 'whereLeetLB', 'whereToUseL33t'],
['profile', 'leetLevelLB', 'l33tLevel', parseInt],
['profile', 'hashAlgorithmLB', 'hashAlgorithm', renameHashAlgorithm, renameHashAlgorithm],
['profile', 'passwordLength', 'passwordLength', parseInt],
['profile', 'usernameTB', 'username'],
['profile', 'counter', 'modifier'],
['profile', 'charset', 'selectedCharset'],
['profile', 'prefix', 'passwordPrefix'],
['profile', 'suffix', 'passwordSuffix'],
['default', 'protocolCB', 'url_protocol', strToBool],
['default', 'subdomainCB', 'url_subdomain', strToBool],
['default', 'domainCB', 'url_domain', strToBool],
['default', 'pathCB', 'url_path', strToBool]
],

// use FF as key for lookup
getImportOpts: function () {
var rv = {};
for(var i=0;i<this.attrs.length;i++){
rv[this.attrs[i][1].toLowerCase()] = {name: this.attrs[i][2], convert: this.attrs[i][3]};
}
return rv;
},

// use option group as key for separate lists
getExportOpts: function () {
var rv = {};
for(var i=0;i<this.attrs.length;i++){
var k = this.attrs[i][0];
if(!rv[k]) rv[k] = [];
rv[k].push({to: this.attrs[i][1], from: this.attrs[i][2], convert: this.attrs[i][4]});
}
return rv;
}
}

RdfImporter.loadDoc = function(rdf) {
var profiles = [],
defaultProfile = {},
settings = {},
that = this;
fromChrome = false,
settings = {};

// check over every Description, but will ignore groups and anything without
// settings/profile attributes
$(rdf).find('RDF\\:Description').each(function(){
var prof = {};
var prof = {},
attrMap = RdfImporter.getImportOpts();
for(var i=0;i<this.attributes.length;i++){
// remove namespace
var attrName = this.attributes[i].name.replace(/.*:/g,''),
opts = RdfImporter.attrMap[attrName],
opts = attrMap[attrName],
val = this.attributes[i].value;
if(opts){
prof[opts.name] = opts.convert ? opts.convert(val) : val;
Expand Down Expand Up @@ -132,15 +132,23 @@ RdfImporter.loadDoc = function(rdf) {
}else if(prof.selectedCharset){
if(prof.rdf_about == 'http://passwordmaker.mozdev.org/defaults'){
defaultProfile = prof;
}else{
// chrome export sets rdf_about to CHROME0, CHROME1, etc.
if(prof.rdf_about.indexOf('CHROME') != -1){ fromChrome = true; }

profiles.push(prof);
}
profiles.push(prof);
}
});

// FF version uses a "default" profile that has attributes we need for each
// profile (such as url_{protocol,subdomain,domain,path})
for(var i=0;i<profiles.length;i++){
profiles[i] = $.extend(new Profile(), defaultProfile, profiles[i]);
// chrome -> chrome doesn't need "default" profile. would create duplicate.
if(!fromChrome){
profiles.unshift(defaultProfile);
// FF version uses a "default" profile that has attributes we need for each
// profile (such as url_{protocol,subdomain,domain,path})
for(var i=0;i<profiles.length;i++){
profiles[i] = $.extend(new Profile(), defaultProfile, profiles[i]);
}
}

return {settings: settings, profiles: profiles};
Expand All @@ -160,3 +168,80 @@ RdfImporter.saveSettings = function(settings) {
Settings.setHidePassword(settings.hideMasterPassword);
Settings.setStoreLocation(settings.storeLocation);
}

RdfImporter.dumpDoc = function() {
var rv = "<?xml version=\"1.0\"?>"+
"<RDF:RDF xmlns:NS1=\"http://passwordmaker.mozdev.org/rdf#\"\n"+
" xmlns:NC=\"http://home.netscape.com/NC-rdf#\"\n"+
" xmlns:RDF=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n";
rv += dumpedProfilesToRdf(dumpedProfiles());
rv += "</RDF:RDF>\n";
return rv;
}

// get profiles as list of objects w/ FF names as keys
function dumpedProfiles() {
var profiles = Settings.getProfiles(),
dumpProfiles = [],
expOpts = RdfImporter.getExportOpts();

for(var i=0;i<profiles.length;i++){
var prof = profiles[i],
newProf = {},
attrMap = expOpts['profile'].concat(expOpts['default']);

// regular attributes
for(var j=0;j<attrMap.length;j++){
var opts = attrMap[j],
val = prof[opts.from];
newProf[opts.to] = opts.convert ? opts.convert(val) : val;
}

// patterns
if(prof.siteList){
var pats = $.trim(prof.siteList).split(' ');
for(var j=0;j<pats.length;j++){
var pat = pats[j],
ptype = (pat[0] == '/' && pat[pat.length-1] == '/') ? 'regex' : 'wildcard';

newProf['pattern' + j] = ptype == 'regex' ? pat.substring(1, pat.length-1) : pat;
newProf['patternenabled' + j] = 'true';
newProf['patterndesc' + j] = '';
newProf['patterntype' + j] = ptype;
}
}

dumpProfiles.push(newProf);
}

return dumpProfiles;
}

function dumpedProfilesToRdf(profiles) {
var rv = '',
abouts = [];
// use first as defaults profile, necessary for FF
profiles.unshift($.extend({}, profiles[0], {name: 'Defaults'}));
for(var i=0;i<profiles.length;i++) {
var about = (i == 0) ? "http://passwordmaker.mozdev.org/defaults" : 'rdf:#$CHROME' + i;
abouts.push(about);

rv += "<RDF:Description RDF:about=\"" + attrEscape(about) + "\"\n";
for(var key in profiles[i]) {
rv += " NS1:" + key + "=\"" + attrEscape(profiles[i][key]) + "\"\n ";
}
rv += " />\n";
}

rv += "<RDF:Seq RDF:about=\"http://passwordmaker.mozdev.org/accounts\">\n";
for(var i=0;i<abouts.length;i++){
rv += "<RDF:li RDF:resource=\"" + attrEscape(abouts[i]) + "\"/>\n";
}
rv += "</RDF:Seq>\n";

return rv;
}

function attrEscape(txt){
return $('<div/>').text(txt).html().replace(/"/g, "&quot;");
}

0 comments on commit 1a1a86a

Please sign in to comment.