summaryrefslogtreecommitdiff
path: root/frontend/beta
Side-by-side diff
Diffstat (limited to 'frontend/beta') (more/less context) (show whitespace changes)
-rw-r--r--frontend/beta/js/Clipperz/Base.js28
-rw-r--r--frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js2
-rw-r--r--frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js4
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js22
-rw-r--r--frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js2
5 files changed, 47 insertions, 11 deletions
diff --git a/frontend/beta/js/Clipperz/Base.js b/frontend/beta/js/Clipperz/Base.js
index cf40314..1c6faa1 100644
--- a/frontend/beta/js/Clipperz/Base.js
+++ b/frontend/beta/js/Clipperz/Base.js
@@ -1,303 +1,331 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz 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 Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
if (typeof(Clipperz.Base) == 'undefined') { Clipperz.Base = {}; }
Clipperz.Base.VERSION = "0.1";
Clipperz.Base.NAME = "Clipperz.Base";
MochiKit.Base.update(Clipperz.Base, {
//-------------------------------------------------------------------------
'__repr__': function () {
return "[" + this.NAME + " " + this.VERSION + "]";
},
//-------------------------------------------------------------------------
'toString': function () {
return this.__repr__();
},
//-------------------------------------------------------------------------
'trim': function (aValue) {
return aValue.replace(/^\s+|\s+$/g, "");
},
//-------------------------------------------------------------------------
'stringToByteArray': function (aValue) {
var result;
var i, c;
result = [];
c = aValue.length;
for (i=0; i<c; i++) {
result[i] = aValue.charCodeAt(i);
}
return result;
},
//.........................................................................
'byteArrayToString': function (anArrayOfBytes) {
var result;
var i, c;
result = "";
c = anArrayOfBytes.length;
for (i=0; i<c; i++) {
result += String.fromCharCode(anArrayOfBytes[i]);
}
return result;
},
//-------------------------------------------------------------------------
'getValueForKeyInFormContent': function (aFormContent, aKey) {
return aFormContent[1][MochiKit.Base.find(aFormContent[0], aKey)];
},
//-------------------------------------------------------------------------
'indexOfObjectInArray': function(anObject, anArray) {
var result;
var i, c;
result = -1;
c = anArray.length;
for (i=0; ((i<c) && (result < 0)); i++) {
if (anArray[i] === anObject) {
result = i;
}
}
return result;
},
'removeObjectAtIndexFromArray': function(anIndex, anArray) {
anArray.splice(anIndex, 1);
},
'removeObjectFromArray': function(anObject, anArray) {
var objectIndex;
objectIndex = Clipperz.Base.indexOfObjectInArray(anObject, anArray);
if (objectIndex > -1) {
Clipperz.Base.removeObjectAtIndexFromArray(objectIndex, anArray);
} else {
// jslog.error("Trying to remove an object not present in the array");
// TODO: raise an exception
}
},
'removeFromArray': function(anArray, anObject) {
return Clipperz.Base.removeObjectFromArray(anObject, anArray);
},
//-------------------------------------------------------------------------
'splitStringAtFixedTokenSize': function(aString, aTokenSize) {
var result;
var stringToProcess;
stringToProcess = aString;
result = [];
if (stringToProcess != null) {
while (stringToProcess.length > aTokenSize) {
result.push(stringToProcess.substring(0, aTokenSize));
stringToProcess = stringToProcess.substring(aTokenSize);
}
result.push(stringToProcess);
}
return result;
},
//-------------------------------------------------------------------------
'objectType': function(anObject) {
var result;
if (anObject == null) {
result = null;
} else {
result = typeof(anObject);
if (result == "object") {
if (anObject instanceof Array) {
result = 'array'
} else if (anObject.constructor == Boolean) {
result = 'boolean'
} else if (anObject instanceof Date) {
result = 'date'
} else if (anObject instanceof Error) {
result = 'error'
} else if (anObject instanceof Function) {
result = 'function'
} else if (anObject.constructor == Number) {
result = 'number'
} else if (anObject.constructor == String) {
result = 'string'
} else if (anObject instanceof Object) {
result = 'object'
} else {
throw Clipperz.Base.exception.UnknownType;
}
}
}
return result;
},
//-------------------------------------------------------------------------
'escapeHTML': function(aValue) {
var result;
result = aValue;
result = result.replace(/</g, "&lt;");
result = result.replace(/>/g, "&gt;");
return result;
},
//-------------------------------------------------------------------------
'deepClone': function(anObject) {
var result;
result = Clipperz.Base.evalJSON(Clipperz.Base.serializeJSON(anObject));
return result;
},
//-------------------------------------------------------------------------
'evalJSON': function(aString) {
/*
var result;
// check for XSS injection
if (/<script>/.test(aString)) {
throw "error";
}
if (/<iframe>/.test(aString)) {
throw "error";
}
result = MochiKit.Base.evalJSON(aString);
return result;
*/
// return MochiKit.Base.evalJSON(aString);
return JSON2.parse(aString);
},
'serializeJSON': function(anObject) {
// return MochiKit.Base.serializeJSON(anObject);
return JSON2.stringify(anObject);
},
//-------------------------------------------------------------------------
'sanitizeString': function(aValue) {
var result;
if (Clipperz.Base.objectType(aValue) == 'string') {
result = aValue;
result = result.replace(/</img,"&lt;");
result = result.replace(/>/img,"&gt;");
} else {
result = aValue;
}
return result;
},
+ 'javascriptInjectionPattern': new RegExp("javascript:\/\/\"", "g"),
+
+ 'sanitizeUrl': function(aValue) {
+ var result;
+
+ if ((aValue != null) && this.javascriptInjectionPattern.test(aValue)) {
+ result = aValue.replace(this.javascriptInjectionPattern, '');
+ console.log("sanitized url", aValue, result);
+ } else {
+ result = aValue;
+ }
+
+ return result;
+ },
+
+ 'sanitizeFavicon': function(aValue) {
+ var result;
+
+ if ((aValue != null) && this.javascriptInjectionPattern.test(aValue)) {
+ result = aValue.replace(this.javascriptInjectionPattern, '');
+ console.log("sanitized favicon", aValue, result);
+ } else {
+ result = aValue;
+ }
+
+ return result;
+ },
+
//-------------------------------------------------------------------------
'exception': {
'AbstractMethod': new MochiKit.Base.NamedError("Clipperz.Base.exception.AbstractMethod"),
'UnknownType': new MochiKit.Base.NamedError("Clipperz.Base.exception.UnknownType"),
'VulnerabilityIssue': new MochiKit.Base.NamedError("Clipperz.Base.exception.VulnerabilityIssue")
},
//-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
MochiKit.Base.registerComparator('Object dummy comparator',
function(a, b) {
return ((a.constructor == Object) && (b.constructor == Object));
},
function(a, b) {
var result;
var aKeys;
var bKeys;
//MochiKit.Logging.logDebug(">>> comparator");
//MochiKit.Logging.logDebug("- a: " + Clipperz.Base.serializeJSON(a));
//MochiKit.Logging.logDebug("- b: " + Clipperz.Base.serializeJSON(a));
aKeys = MochiKit.Base.keys(a).sort();
bKeys = MochiKit.Base.keys(b).sort();
result = MochiKit.Base.compare(aKeys, bKeys);
//if (result != 0) {
// MochiKit.Logging.logDebug("- comparator 'keys':");
// MochiKit.Logging.logDebug("- comparator aKeys: " + Clipperz.Base.serializeJSON(aKeys));
// MochiKit.Logging.logDebug("- comparator bKeys: " + Clipperz.Base.serializeJSON(bKeys));
//}
if (result == 0) {
var i, c;
c = aKeys.length;
for (i=0; (i<c) && (result == 0); i++) {
result = MochiKit.Base.compare(a[aKeys[i]], b[bKeys[i]]);
//if (result != 0) {
// MochiKit.Logging.logDebug("- comparator 'values':");
// MochiKit.Logging.logDebug("- comparator a[aKeys[i]]: " + Clipperz.Base.serializeJSON(a[aKeys[i]]));
// MochiKit.Logging.logDebug("- comparator b[bKeys[i]]: " + Clipperz.Base.serializeJSON(b[bKeys[i]]));
//}
}
}
//MochiKit.Logging.logDebug("<<< comparator - result: " + result);
return result;
},
true
);
diff --git a/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js b/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js
index 2295d3f..369b9ce 100644
--- a/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js
+++ b/frontend/beta/js/Clipperz/PM/BookmarkletProcessor.js
@@ -1,283 +1,283 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz 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 Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
//if (typeof(Clipperz.PM.BookmarkletProcessor) == 'undefined') { Clipperz.PM.BookmarkletProcessor = {}; }
//if (typeof(Clipperz.PM.BookmarkletProcessor.versions) == 'undefined') { Clipperz.PM.BookmarkletProcessor.versions = {}; }
/*
Clipperz.PM.BookmarkletProcessor.versions['abstract'] = function(anUser, aConfiguration) {
this._user = anUser;
this._configuration = aConfiguration;
this._recordTitle = null;
this._record = null;
this._editableFields = null;
return this;
}
Clipperz.PM.BookmarkletProcessor.versions['abstract'].prototype = MochiKit.Base.update(null, {
'toString': function() {
return "BookmarkletProcessor - " + this.user();
},
//-------------------------------------------------------------------------
'user': function() {
return this._user;
},
//-------------------------------------------------------------------------
'configuration': function() {
return this._configuration;
},
//-------------------------------------------------------------------------
'record': function() {
throw Clipperz.Base.exception.AbstractMethod;
},
//-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
*/
Clipperz.PM.BookmarkletProcessor = function(anUser, aConfiguration) {
this._user = anUser;
this._configuration = aConfiguration;
this._recordTitle = null;
this._record = null;
this._editableFields = null;
this._favicon = null;
return this;
}
Clipperz.PM.BookmarkletProcessor.prototype = MochiKit.Base.update(null, {
'toString': function() {
return "BookmarkletProcessor - " + this.user();
},
//-------------------------------------------------------------------------
'user': function() {
return this._user;
},
//-------------------------------------------------------------------------
'configuration': function() {
return this._configuration;
},
//-------------------------------------------------------------------------
'recordTitle': function() {
if (this._recordTitle == null) {
this._recordTitle = this.configuration().page.title;
}
return this._recordTitle;
},
//-------------------------------------------------------------------------
'fields': function() {
return this.configuration().form.inputs;
},
//-------------------------------------------------------------------------
'editableFields': function() {
if (this._editableFields == null) {
this._editableFields = MochiKit.Base.filter(function(aField) {
var result;
var type;
type = aField['type'].toLowerCase();
result = ((type != 'hidden') && (type != 'submit') && (type != 'checkbox') && (type != 'radio') && (type != 'select'));
return result;
}, this.fields())
}
return this._editableFields;
},
//-------------------------------------------------------------------------
'hostname': function() {
if (this._hostname == null) {
var actionUrl;
- actionUrl = this.configuration()['form']['attributes']['action'];
+ actionUrl = Clipperz.Base.sanitizeUrl(this.configuration()['form']['attributes']['action']);
//MochiKit.Logging.logDebug("+++ actionUrl: " + actionUrl);
this._hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1');
}
return this._hostname;
},
'favicon': function() {
if (this._favicon == null) {
this._favicon = "http://" + this.hostname() + "/favicon.ico";
//MochiKit.Logging.logDebug("+++ favicon: " + this._favicon);
}
return this._favicon;
},
//-------------------------------------------------------------------------
'record': function() {
if (this._record == null) {
var record;
var recordVersion;
var directLogin;
var bindings;
var i,c;
record = new Clipperz.PM.DataModel.Record({
label:this.recordTitle(),
notes:"",
user:this.user()
});
recordVersion = new Clipperz.PM.DataModel.RecordVersion(record, {})
record.setCurrentVersion(recordVersion);
bindings = {};
c = this.editableFields().length;
for (i=0; i<c; i++) {
var formField;
var recordField;
//MochiKit.Logging.logDebug(">>> adding a field");
formField = this.editableFields()[i];
recordField = new Clipperz.PM.DataModel.RecordField({
recordVersion:recordVersion,
label:formField['name'],
value:formField['value'],
type:Clipperz.PM.Strings.inputTypeToRecordFieldType[formField['type']],
hidden:false
});
recordVersion.addField(recordField);
bindings[formField['name']] = recordField.key();
//MochiKit.Logging.logDebug("<<< adding a field");
}
directLogin = new Clipperz.PM.DataModel.DirectLogin({
record:record,
label:this.recordTitle() + Clipperz.PM.Strings['newDirectLoginLabelSuffix'],
// bookmarkletVersion:this.version(),
bookmarkletVersion:'0.2',
favicon:this.favicon(),
formData:this.configuration()['form'],
bindingData:bindings
});
record.addDirectLogin(directLogin);
this.user().addRecord(record);
this._record = record;
}
return this._record;
},
//-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
//#############################################################################
Clipperz.PM.BookmarkletProcessor.createRecordFromBookmarkletConfiguration = function(anUser, aConfiguration) {
var processor;
processor = new Clipperz.PM.BookmarkletProcessor(anUser, aConfiguration);
return processor.record();
};
//-----------------------------------------------------------------------------
Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration = function(aConfiguration) {
var result;
// throw "XSS Bookmarklet attempt";
result = aConfiguration;
return result;
};
//-----------------------------------------------------------------------------
Clipperz.PM.BookmarkletProcessor.checkBookmarkletConfiguration = function(aConfiguration, aButton, aCallback) {
var result;
try {
result = Clipperz.Base.evalJSON(aConfiguration);
result = Clipperz.PM.BookmarkletProcessor.sanitizeBookmarkletConfiguration(result);
if (result['version'] != '0.2.3') {
throw "WrongBookmarkletVersion";
}
} catch (exception) {
var title;
var message;
if (exception == "WrongBookmarkletVersion") {
title = Clipperz.PM.Strings['newRecordPanelWrongBookmarkletVersionExceptionTitle'];
message = Clipperz.PM.Strings['newRecordPanelWrongBookmarkletVersionExceptionMessage'];
} else {
title = Clipperz.PM.Strings['newRecordPanelGeneralExceptionTitle'];
message = Clipperz.PM.Strings['newRecordPanelGeneralExceptionMessage'];
}
Clipperz.PM.Components.MessageBox().show({
title:title,
text:message,
width:240,
fn:aCallback,
closable:false,
showProgressBar:false,
showCloseButton:false,
buttons:{'ok':Clipperz.PM.Strings['newRecordPanelExceptionPanelCloseButtonLabel']}
}, aButton);
throw exception;
}
return result;
};
//-----------------------------------------------------------------------------
diff --git a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js
index 0e4640e..a5a4697 100644
--- a/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js
+++ b/frontend/beta/js/Clipperz/PM/Components/RecordDetail/DirectLoginBindingComponent.js
@@ -1,169 +1,169 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz 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 Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; }
if (typeof(Clipperz.PM.Components.RecordDetail) == 'undefined') { Clipperz.PM.Components.RecordDetail = {}; }
//#############################################################################
Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent = function(anElement, args) {
//MochiKit.Logging.logDebug(">>> new DirectLoginBindingComponent");
args = args || {};
Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent.superclass.constructor.call(this, anElement, args);
this._directLoginBinding = args.directLoginBinding || null;
this.render();
Clipperz.NotificationCenter.register(this.record(), 'addNewRecordField', this, 'syncAndUpdateEditMode');
Clipperz.NotificationCenter.register(this.record(), 'removedField', this, 'syncAndUpdateEditMode');
Clipperz.NotificationCenter.register(this.record(), 'updatedFieldLabel', this, 'syncAndUpdateEditMode');
//MochiKit.Logging.logDebug("<<< new DirectLoginBindingComponent");
return this;
}
//=============================================================================
YAHOO.extendX(Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent, Clipperz.PM.Components.RecordDetail.AbstractComponent, {
'toString': function() {
return "Clipperz.PM.Components.RecordDetail.DirectLoginBindingComponent component";
},
//-------------------------------------------------------------------------
'directLoginBinding': function() {
return this._directLoginBinding;
},
//-------------------------------------------------------------------------
'render': function() {
// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'span', style:'font-weight:bold;', html:this.directLoginBinding().key()})
// Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'span', html:this.directLoginBinding().value()})
//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.render");
Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', cls:'directLoginBindingLabelTD', children:[
{tag:'span', html:this.directLoginBinding().key()}
]});
//MochiKit.Logging.logDebug("--- DirectLoginBindingComponent.render - 1");
Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'td', cls:'directLoginBindingValueTD', children:[
{tag:'div', id:this.getId('editModeBox'), children:[
{tag:'select', id:this.getId('select'), children:this.recordFieldOptions()}
]},
{tag:'div', id:this.getId('viewModeBox'), children:[
{tag:'span', id:this.getId('viewValue'), html:""}
]}
]});
//MochiKit.Logging.logDebug("--- DirectLoginBindingComponent.render - 2");
this.getElement('editModeBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
this.getElement('viewModeBox').setVisibilityMode(YAHOO.ext.Element.DISPLAY);
this.update();
//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.render");
},
//-------------------------------------------------------------------------
'recordFieldOptions': function() {
var result;
var option;
var recordFieldKey;
var recordFields;
//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.recordFieldOptions");
recordFields = this.directLoginBinding().directLogin().record().currentVersion().fields();
result = [];
option = {tag:'option', value:null, html:'---'};
result.push(option);
for (recordFieldKey in recordFields) {
// TODO: remove the value: field and replace it with element.dom.value = <some value>
- option = {tag:'option', value:recordFieldKey, html:recordFields[recordFieldKey].label()}
+ option = {tag:'option', value:recordFieldKey, html:Clipperz.Base.sanitizeString(recordFields[recordFieldKey].label())}
if (recordFieldKey == this.directLoginBinding().fieldKey()) {
option['selected'] = true;
}
result.push(option);
}
//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.recordFieldOptions");
return result;
},
//-------------------------------------------------------------------------
'syncAndUpdateEditMode': function() {
this.synchronizeComponentValues();
this.updateEditMode();
},
'updateEditMode': function() {
var selectElementBox;
//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.updateEditMode");
this.getElement('viewModeBox').hide();
selectElementBox = this.getElement('editModeBox');
selectElementBox.update("");
Clipperz.YUI.DomHelper.append(selectElementBox.dom, {tag:'select', id:this.getId('select'), children:this.recordFieldOptions()});
/*
selectElement = this.getElement('select');
selectElement.update("");
MochiKit.Iter.forEach(this.recordFieldOptions(), function(anOption) {
Clipperz.YUI.DomHelper.append(selectElement.dom, anOption);
});
*/
this.getElement('editModeBox').show();
//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.updateEditMode");
},
//-------------------------------------------------------------------------
'updateViewMode': function() {
//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.updateViewMode");
this.getElement('editModeBox').hide();
this.getElement('viewModeBox').show();
- this.getElement('viewValue').update(this.directLoginBinding().field().label());
+ this.getElement('viewValue').update(Clipperz.Base.sanitizeString(this.directLoginBinding().field().label()));
//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.updateViewMode");
},
//-------------------------------------------------------------------------
'synchronizeComponentValues': function() {
//MochiKit.Logging.logDebug(">>> DirectLoginBindingComponent.synchronizeComponentValues")
//MochiKit.Logging.logDebug("--- DirectLoginBindingComponent.synchronizeComponentValues - 1 - " + this.getId('select'));
this.directLoginBinding().setFieldKey(this.getDom('select').value);
//MochiKit.Logging.logDebug("<<< DirectLoginBindingComponent.synchronizeComponentValues");
},
//-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js b/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js
index c0cfa3c..56d9d59 100644
--- a/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js
+++ b/frontend/beta/js/Clipperz/PM/DataModel/DirectLogin.js
@@ -1,531 +1,539 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz 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 Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
//#############################################################################
Clipperz.PM.DataModel.DirectLogin = function(args) {
//MochiKit.Logging.logDebug(">>> new Clipperz.PM.DataModel.DirectLogin");
//console.log(">>> new Clipperz.PM.DataModel.DirectLogin - args: %o", args);
//console.log("--- formData: %s", Clipperz.Base.serializeJSON(args.formData));
args = args || {};
//MochiKit.Logging.logDebug("--- new Clipperz.PM.DataModel.DirectLogin - args: " + Clipperz.Base.serializeJSON(MochiKit.Base.keys(args)));
this._record = args.record || null;
this._label = args.label || "unnamed record"
this._reference = args.reference || Clipperz.PM.Crypto.randomKey();
- this._favicon = args.favicon || null;
+ this._favicon = Clipperz.Base.sanitizeFavicon(args.favicon) || null;
this._bookmarkletVersion = args.bookmarkletVersion || "0.1";
this._directLoginInputs = null;
this._formValues = args.formValues || {};
this.setFormData(args.formData || null);
//console.log("=== formData: %o", this.formData());
if (args.legacyBindingData == null) {
this.setBindingData(args.bindingData || null);
} else {
this.setLegacyBindingData(args.legacyBindingData);
}
this._fixedFavicon = null;
// this._formValues = args.formValues || (this.hasValuesToSet() ? {} : null);
//MochiKit.Logging.logDebug("<<< new Clipperz.PM.DataModel.DirectLogin");
return this;
}
Clipperz.PM.DataModel.DirectLogin.prototype = MochiKit.Base.update(null, {
'remove': function() {
this.record().removeDirectLogin(this);
},
//-------------------------------------------------------------------------
'record': function() {
return this._record;
},
//-------------------------------------------------------------------------
'user': function() {
return this.record().user();
},
//-------------------------------------------------------------------------
'reference': function() {
return this._reference;
},
//-------------------------------------------------------------------------
'label': function() {
return this._label;
},
'setLabel': function(aValue) {
this._label = aValue;
},
//-------------------------------------------------------------------------
'favicon': function() {
if (this._favicon == null) {
var actionUrl;
var hostname;
- actionUrl = this.formData()['attributes']['action'];
+ actionUrl = this.action();
hostname = actionUrl.replace(/^https?:\/\/([^\/]*)\/.*/, '$1');
- this._favicon = "http://" + hostname + "/favicon.ico";
+ this._favicon = Clipperz.Base.sanitizeFavicon("http://" + hostname + "/favicon.ico");
}
return this._favicon;
},
//-------------------------------------------------------------------------
'fixedFavicon': function() {
var result;
if (this._fixedFavicon == null) {
result = this.favicon();
if (Clipperz_IEisBroken) {
if (this.user().preferences().disableUnsecureFaviconLoadingForIE()) {
if (result.indexOf('https://') != 0) {
result = Clipperz.PM.Strings['defaultFaviconUrl_IE'];
this.setFixedFavicon(result);
}
}
}
} else {
result = this._fixedFavicon;
}
return result;
},
'setFixedFavicon': function(aValue) {
this._fixedFavicon = aValue;
},
+ 'action': function () {
+ var result;
+
+ result = Clipperz.Base.sanitizeUrl(this.formData()['attributes']['action']);
+
+ return result;
+ },
+
//-------------------------------------------------------------------------
'bookmarkletVersion': function() {
return this._bookmarkletVersion;
},
'setBookmarkletVersion': function(aValue) {
this._bookmarkletVersion = aValue;
},
//-------------------------------------------------------------------------
'formData': function() {
return this._formData;
},
'setFormData': function(aValue) {
var formData;
//MochiKit.Logging.logDebug(">>> DirectLogin.setFormData - " + Clipperz.Base.serializeJSON(aValue));
switch (this.bookmarkletVersion()) {
case "0.2":
formData = aValue;
break;
case "0.1":
//MochiKit.Logging.logDebug("--- DirectLogin.setFormData - fixing form data from bookmarklet version 0.1");
formData = this.fixFormDataFromBookmarkletVersion_0_1(aValue);
break;
}
this._formData = aValue;
this.setBookmarkletVersion("0.2");
//MochiKit.Logging.logDebug("--- DirectLogin.setFormData - formData: " + Clipperz.Base.serializeJSON(formData));
if (formData != null) {
var i,c;
this._directLoginInputs = [];
c = formData['inputs'].length;
for (i=0; i<c; i++) {
var directLoginInput;
directLoginInput = new Clipperz.PM.DataModel.DirectLoginInput(this, formData['inputs'][i]);
this._directLoginInputs.push(directLoginInput);
}
}
//MochiKit.Logging.logDebug("<<< DirectLogin.setFormData");
},
'fixFormDataFromBookmarkletVersion_0_1': function(aValue) {
//{"type":"radio", "name":"action", "value":"new-user", "checked":false }, { "type":"radio", "name":"action", "value":"sign-in", "checked":true }
// ||
// \ /
// \/
//{"name":"dominio", "type":"radio", "options":[{"value":"@alice.it", "checked":true}, {"value":"@tin.it", "checked":false}, {"value":"@virgilio.it", "checked":false}, {"value":"@tim.it", "checked":false}]}
var result;
var inputs;
var updatedInputs;
var radios;
//MochiKit.Logging.logDebug(">>> DirectLogin.fixFormDataFromBookmarkletVersion_0_1");
result = aValue;
inputs = aValue['inputs'];
updatedInputs = MochiKit.Base.filter(function(anInput) {
var result;
var type;
type = anInput['type'] || 'text';
result = type.toLowerCase() != 'radio';
return result;
}, inputs);
radios = MochiKit.Base.filter(function(anInput) {
var result;
var type;
type = anInput['type'] || 'text';
result = type.toLowerCase() == 'radio';
return result;
}, inputs);
if (radios.length > 0) {
var updatedRadios;
updatedRadios = {};
MochiKit.Iter.forEach(radios, MochiKit.Base.bind(function(aRadio) {
var radioConfiguration;
radioConfiguration = updatedRadios[aRadio['name']];
if (radioConfiguration == null) {
radioConfiguration = {type:'radio', name:aRadio['name'], options:[]};
updatedRadios[aRadio['name']] = radioConfiguration;
}
// TODO: remove the value: field and replace it with element.dom.value = <some value>
radioConfiguration.options.push({value:aRadio['value'], checked:aRadio['checked']});
if ((aRadio['checked'] == true) && (this.formValues()[aRadio['name']] == null)) {
//MochiKit.Logging.logDebug("+++ setting value '" + aRadio['value'] + "' for key: '" + aRadio['name'] + "'");
this.formValues()[aRadio['name']] = aRadio['value'];
}
}, this))
updatedInputs = MochiKit.Base.concat(updatedInputs, MochiKit.Base.values(updatedRadios));
}
delete result.inputs;
result.inputs = updatedInputs;
//MochiKit.Logging.logDebug("<<< DirectLogin.fixFormDataFromBookmarkletVersion_0_1");
return result;
},
//.........................................................................
'directLoginInputs': function() {
return this._directLoginInputs;
},
//-------------------------------------------------------------------------
'formValues': function() {
return this._formValues;
},
'hasValuesToSet': function() {
var result;
//MochiKit.Logging.logDebug(">>> DirectLogin.hasValuesToSet");
if (this.directLoginInputs() != null) {
result = MochiKit.Iter.some(this.directLoginInputs(), MochiKit.Base.methodcaller('shouldSetValue'));
} else {
result = false;
}
//MochiKit.Logging.logDebug("<<< DirectLogin.hasValuesToSet");
return result;
},
// 'additionalValues': function() {
'inputsRequiringAdditionalValues': function() {
var result;
var inputs;
//MochiKit.Logging.logDebug(">>> DirectLogin.additionalValues");
result = {};
if (this.directLoginInputs() != null) {
inputs = MochiKit.Base.filter(MochiKit.Base.methodcaller('shouldSetValue'), this.directLoginInputs());
MochiKit.Iter.forEach(inputs, function(anInput) {
result[anInput.name()] = anInput;
})
}
//MochiKit.Logging.logDebug("<<< DirectLogin.additionalValues");
return result;
},
//-------------------------------------------------------------------------
'bindingData': function() {
return this._bindingData;
},
'setBindingData': function(aValue) {
//MochiKit.Logging.logDebug(">>> DirectLogin.setBindingData");
if (aValue != null) {
var bindingKey;
this._bindingData = aValue;
this._bindings = {};
for (bindingKey in aValue) {
var directLoginBinding;
directLoginBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, bindingKey, {fieldKey:aValue[bindingKey]});
this._bindings[bindingKey] = directLoginBinding;
}
} else {
var editableFields;
var bindings;
bindings = {};
editableFields = MochiKit.Base.filter(function(aField) {
var result;
var type;
type = aField['type'].toLowerCase();
result = ((type != 'hidden') && (type != 'submit') && (type != 'checkbox') && (type != 'radio') && (type != 'select'));
return result;
}, this.formData().inputs);
MochiKit.Iter.forEach(editableFields, function(anEditableField) {
bindings[anEditableField['name']] = new Clipperz.PM.DataModel.DirectLoginBinding(this, anEditableField['name']);
}, this);
this._bindings = bindings;
}
//MochiKit.Logging.logDebug("<<< DirectLogin.setBindingData");
},
'setLegacyBindingData': function(aValue) {
//MochiKit.Logging.logDebug(">>> DirectLogin.setLegacyBindingData");
var bindingKey;
this._bindingData = aValue;
this._bindings = {};
for (bindingKey in aValue) {
var directLoginBinding;
directLoginBinding = new Clipperz.PM.DataModel.DirectLoginBinding(this, bindingKey, {fieldName:aValue[bindingKey]});
this._bindings[bindingKey] = directLoginBinding;
}
//MochiKit.Logging.logDebug("<<< DirectLogin.setLegacyBindingData");
},
//.........................................................................
'bindings': function() {
return this._bindings;
},
//-------------------------------------------------------------------------
'serializedData': function() {
var result;
var bindingKey;
result = {};
// result.reference = this.reference();
result.label = this.label();
result.favicon = this.favicon() || "";
result.bookmarkletVersion = this.bookmarkletVersion();
result.formData = this.formData();
if (this.hasValuesToSet) {
result.formValues = this.formValues();
}
result.bindingData = {};
for (bindingKey in this.bindings()) {
result.bindingData[bindingKey] = this.bindings()[bindingKey].serializedData();
}
return result;
},
//-------------------------------------------------------------------------
'handleMissingFaviconImage': function(anEvent) {
anEvent.stop();
MochiKit.Signal.disconnectAll(anEvent.src());
this.setFixedFavicon(Clipperz.PM.Strings['defaultFaviconUrl']);
anEvent.src().src = this.fixedFavicon();
},
//=========================================================================
'runHttpAuthDirectLogin': function(aWindow) {
MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function() {
var completeUrl;
var url;
url = this.bindings()['url'].field().value();
if (/^https?\:\/\//.test(url) == false) {
url = 'http://' + url;
}
if (Clipperz_IEisBroken === true) {
completeUrl = url;
} else {
var username;
var password;
username = this.bindings()['username'].field().value();
password = this.bindings()['password'].field().value();
/(^https?\:\/\/)?(.*)/.test(url);
completeUrl = RegExp.$1 + username + ':' + password + '@' + RegExp.$2;
}
MochiKit.DOM.currentWindow().location.href = completeUrl;
}, this));
},
//-------------------------------------------------------------------------
'runSubmitFormDirectLogin': function(aWindow) {
MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function() {
var formElement;
var formSubmitFunction;
var submitButtons;
//MochiKit.Logging.logDebug("### runDirectLogin - 3");
// MochiKit.DOM.currentDocument().write('<html><head><title>' + this.label() + '</title><META http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body></body></html>')
//MochiKit.Logging.logDebug("### runDirectLogin - 3.1");
MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body, MochiKit.DOM.H3(null, "Loading " + this.label() + " ..."));
//MochiKit.Logging.logDebug("### runDirectLogin - 4");
//console.log(this.formData()['attributes']);
formElement = MochiKit.DOM.FORM(MochiKit.Base.update({id:'directLoginForm'}, { 'method':this.formData()['attributes']['method'],
- 'action':this.formData()['attributes']['action']}));
+ 'action': this.action()}));
//MochiKit.Logging.logDebug("### runDirectLogin - 5");
formSubmitFunction = MochiKit.Base.method(formElement, 'submit');
//MochiKit.Logging.logDebug("### runDirectLogin - 6");
MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body,
MochiKit.DOM.DIV({style:'display:none; visibility:hidden;'}, formElement)
);
//MochiKit.Logging.logDebug("### runDirectLogin - 7");
MochiKit.DOM.appendChildNodes(formElement, MochiKit.Base.map( MochiKit.Base.methodcaller("formConfiguration"),
this.directLoginInputs()));
//MochiKit.Logging.logDebug("### runDirectLogin - 8");
submitButtons = MochiKit.Base.filter(function(anInputElement) {
//MochiKit.Logging.logDebug("### runDirectLogin - 8.1 - " + anInputElement);
//MochiKit.Logging.logDebug("### runDirectLogin - 8.2 - " + anInputElement.tagName);
//MochiKit.Logging.logDebug("### runDirectLogin - 8.3 - " + anInputElement.getAttribute('type'));
return ((anInputElement.tagName.toLowerCase() == 'input') && (anInputElement.getAttribute('type').toLowerCase() == 'submit'));
}, formElement.elements)
//MochiKit.Logging.logDebug("### runDirectLogin - 9");
if (submitButtons.length == 0) {
//MochiKit.Logging.logDebug("### OLD submit")
if (Clipperz_IEisBroken == true) {
//MochiKit.Logging.logDebug("### runDirectLogin - 10");
formElement.submit();
} else {
//MochiKit.Logging.logDebug("### runDirectLogin - 11");
formSubmitFunction();
}
} else {
//MochiKit.Logging.logDebug("### NEW submit")
submitButtons[0].click();
}
}, this));
},
//-------------------------------------------------------------------------
'runDirectLogin': function(aNewWindow) {
var newWindow;
//console.log("formData.attributes", this.formData()['attributes']);
// if (/^javascript/.test(this.formData()['attributes']['action'])) {
- if ((/^(https?|webdav|ftp)\:/.test(this.formData()['attributes']['action']) == false) &&
- (this.formData()['attributes']['type'] != 'http_auth'))
- {
+ if ((/^(https?|webdav|ftp)\:/.test(this.action()) == false) &&
+ (this.formData()['attributes']['type'] != 'http_auth')
+ ) {
var messageBoxConfiguration;
if (typeof(aNewWindow) != 'undefined') {
aNewWindow.close();
}
messageBoxConfiguration = {};
messageBoxConfiguration.title = Clipperz.PM.Strings['VulnerabilityWarning_Panel_title'];
messageBoxConfiguration.msg = Clipperz.PM.Strings['VulnerabilityWarning_Panel_message'];
messageBoxConfiguration.animEl = YAHOO.ext.Element.get("mainDiv");
messageBoxConfiguration.progress = false;
messageBoxConfiguration.closable = false;
messageBoxConfiguration.buttons = {'cancel': Clipperz.PM.Strings['VulnerabilityWarning_Panel_buttonLabel']};
Clipperz.YUI.MessageBox.show(messageBoxConfiguration);
throw Clipperz.Base.exception.VulnerabilityIssue;
}
//MochiKit.Logging.logDebug("### runDirectLogin - 1 : " + Clipperz.Base.serializeJSON(this.serializedData()));
if (typeof(aNewWindow) == 'undefined') {
newWindow = window.open(Clipperz.PM.Strings['directLoginJumpPageUrl'], "");
} else {
newWindow = aNewWindow;
}
//MochiKit.Logging.logDebug("### runDirectLogin - 2");
if (this.formData()['attributes']['type'] == 'http_auth') {
this.runHttpAuthDirectLogin(newWindow);
} else {
this.runSubmitFormDirectLogin(newWindow)
}
},
//-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});
diff --git a/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js
index 236d7c9..ba302da 100644
--- a/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js
+++ b/frontend/beta/js/Clipperz/PM/DataModel/DirectLoginReference.js
@@ -1,187 +1,187 @@
/*
Copyright 2008-2013 Clipperz Srl
This file is part of Clipperz, the online password manager.
For further information about its features and functionalities please
refer to http://www.clipperz.com.
* Clipperz is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
* Clipperz 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 Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
*/
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
if (typeof(Clipperz.PM.DataModel) == 'undefined') { Clipperz.PM.DataModel = {}; }
//#############################################################################
Clipperz.PM.DataModel.DirectLoginReference = function(args) {
args = args || {};
//MochiKit.Logging.logDebug(">>> new DirectLoginReference: " + Clipperz.Base.serializeJSON(MochiKit.Base.keys(args)));
//MochiKit.Logging.logDebug(">>> new DirectLoginReference - record: " + args.record);
this._user = args.user;
if (args.directLogin != null) {
this._reference = args.directLogin.reference();
this._recordReference = args.directLogin.record().reference();
this._label = args.directLogin.label();
this._favicon = args.directLogin.favicon() || null;
this._directLogin = args.directLogin;
this._record = args.directLogin.record();
} else {
this._reference = args.reference;
this._recordReference = args.record;
this._label = args.label;
- this._favicon = args.favicon || null;
+ this._favicon = Clipperz.Base.sanitizeFavicon(args.favicon) || null;
this._directLogin = null;
this._record = null;
}
this._fixedFavicon = null;
return this;
}
Clipperz.PM.DataModel.DirectLoginReference.prototype = MochiKit.Base.update(null, {
'user': function() {
return this._user;
},
//-------------------------------------------------------------------------
'reference': function() {
return this._reference;
},
//-------------------------------------------------------------------------
'synchronizeValues': function(aDirectLogin) {
this._label = aDirectLogin.label();
this._favicon = aDirectLogin.favicon();
},
//-------------------------------------------------------------------------
'label': function() {
return this._label;
},
//-------------------------------------------------------------------------
'recordReference': function() {
return this._recordReference;
},
//-------------------------------------------------------------------------
'record': function() {
//MochiKit.Logging.logDebug(">>> DirectLoginReference.record");
if (this._record == null) {
this._record = this.user().records()[this.recordReference()];
}
//MochiKit.Logging.logDebug("<<< DirectLoginReference.record");
return this._record;
},
//-------------------------------------------------------------------------
'favicon': function() {
return this._favicon;
},
//-------------------------------------------------------------------------
'fixedFavicon': function() {
var result;
if (this._fixedFavicon == null) {
result = this.favicon();
if (Clipperz_IEisBroken && (this.user().preferences().disableUnsecureFaviconLoadingForIE()) && (result.indexOf('https://') != 0)) {
result = Clipperz.PM.Strings['defaultFaviconUrl_IE'];
this.setFixedFavicon(result);
}
} else {
result = this._fixedFavicon;
}
return result;
},
'setFixedFavicon': function(aValue) {
this._fixedFavicon = aValue;
},
//-------------------------------------------------------------------------
'setupJumpPageWindow': function(aWindow) {
//MochiKit.Logging.logDebug(">>> DirectLoginReference.setupJumpPageWindow - " + aWindow);
try {
MochiKit.DOM.withWindow(aWindow, MochiKit.Base.bind(function() {
MochiKit.DOM.appendChildNodes(MochiKit.DOM.currentDocument().body,
MochiKit.DOM.H1(null, "Loading " + this.label())
);
}, this));
} catch(e) {
MochiKit.Logging.logDebug("EXCEPTION: " + e);
}
//MochiKit.Logging.logDebug("<<< DirectLoginReference.setupJumpPageWindow");
},
//-------------------------------------------------------------------------
'deferredDirectLogin': function() {
var deferredResult;
//MochiKit.Logging.logDebug(">>> DirectLoginReference.deferredDirectLogin - " + this);
deferredResult = new MochiKit.Async.Deferred();
//MochiKit.Logging.logDebug("--- DirectLoginReference.deferredDirectLogin - 1");
deferredResult.addCallback(MochiKit.Base.method(this.record(), 'deferredData'));
//MochiKit.Logging.logDebug("--- DirectLoginReference.deferredDirectLogin - 2");
deferredResult.addCallback(function(aRecord, aDirectLoginReference) {
return aRecord.directLogins()[aDirectLoginReference];
}, this.record(), this.reference());
//MochiKit.Logging.logDebug("--- DirectLoginReference.deferredDirectLogin - 3");
deferredResult.callback();
//MochiKit.Logging.logDebug("<<< DirectLoginReference.deferredDirectLogin");
return deferredResult;
},
//-------------------------------------------------------------------------
'handleMissingFaviconImage': function(anEvent) {
//MochiKit.Logging.logDebug(">>> DirectLoginReference.handleMissingFaviconImage");
anEvent.stop();
MochiKit.Signal.disconnectAll(anEvent.src());
this.setFixedFavicon(Clipperz.PM.Strings['defaultFaviconUrl']);
//MochiKit.Logging.logDebug("--- DirectLoginReference.handleMissingFaviconImage - fixedFavicon: " + this.fixedFavicon());
//MochiKit.Logging.logDebug("--- DirectLoginReference.handleMissingFaviconImage - anEvent.src().src: " + anEvent.src().src);
// MochiKit.DOM.swapDOM(anEvent.src(), MochiKit.DOM.IMG({src:'this.fixedFavicon()'}));
anEvent.src().src = this.fixedFavicon();
//MochiKit.Logging.logDebug("<<< DirectLoginReference.handleMissingFaviconImage");
},
//-------------------------------------------------------------------------
__syntaxFix__: "syntax fix"
});