/* Copyright 2008-2011 Clipperz Srl This file is part of Clipperz Community Edition. Clipperz Community Edition is an online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. * Clipperz Community Edition 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 Community Edition 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 Community Edition. If not, see . */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } //============================================================================= Clipperz.ByteArray_abstract = function(args) { return this; } Clipperz.ByteArray_abstract.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- 'toString': function() { return "Clipperz.ByteArray_abstract"; }, //------------------------------------------------------------------------- 'equals': function(aValue) { return (this.compare(aValue) == 0); }, //------------------------------------------------------------------------- 'compare': function(aValue) { var result; var i; result = MochiKit.Base.compare(this.length(), aValue.length()); i = this.length(); while ((result == 0) && (i>0)) { i--; result = MochiKit.Base.compare(this.byteAtIndex(i), aValue.byteAtIndex(i)); } return result; }, //------------------------------------------------------------------------- 'clone': function() { throw Clipperz.Base.exception.AbstractMethod; }, //------------------------------------------------------------------------- 'newInstance': function() { throw Clipperz.Base.exception.AbstractMethod; }, //------------------------------------------------------------------------- 'reset': function() { throw Clipperz.Base.exception.AbstractMethod; }, //------------------------------------------------------------------------- 'length': function() { throw Clipperz.Base.exception.AbstractMethod; }, //------------------------------------------------------------------------- 'checkValue': function(aValue) { if ((aValue & 0xff) != aValue) { MochiKit.Logging.logError("Clipperz.ByteArray.appendByte: the provided value (0x" + aValue.toString(16) + ") is not a byte value."); throw Clipperz.ByteArray.exception.InvalidValue; } }, //------------------------------------------------------------------------- 'xorMergeWithBlock': function(aBlock, anAllignment, paddingMode) { var result; var a, b; var aLength; var bLength; var i, c; if (this.length() > aBlock.length()) { a = this; b = aBlock; } else { a = aBlock; b = this; } aLength = a.length(); bLength = b.length(); if (aLength != bLength) { if (paddingMode == 'truncate') { if (anAllignment == 'left') { a = a.split(0, bLength); } else { a = a.split(aLength - bLength); } } else { var ii, cc; var padding; // padding = new Clipperz.ByteArray(); padding = this.newInstance(); cc = aLength - bLength; for (ii=0; ii> 8) & 0xff, (aValue >> 16) & 0xff, (aValue >> 24) & 0xff ); // little endian } else { result = this.appendBytes( (aValue >> 24) & 0xff, (aValue >> 16) & 0xff, (aValue >> 8) & 0xff, (aValue) & 0xff ); // big endian - DEFAULT } return result; }, 'appendWords': function(args) { var values; var i,c; if (args.constructor == Array) { values = args; } else { values = arguments; } c = values.length; for (i=0; i 0) { selectedByteMask = (1 << bitPositionInSelectedByte); } else { selectedByteMask = 1; } result = selectedByte & selectedByteMask ? 1 : 0; //console.log("aBitPosition: " + aBitPosition + ", length: " + this.length() + ", bytePosition: " + bytePosition + ", bitPositionInSelectedByte: " + bitPositionInSelectedByte + ", selectedByteMask: " + selectedByteMask); return result; }, //------------------------------------------------------------------------- 'bitBlockAtIndexWithSize': function(aBitPosition, aSize) { var result; var bitValue; var i,c; result = 0; c = aSize; for (i=0; i> 4); if (value3 != -1) { byte2 = ((value2 & 0x0f) << 4) | ((value3 & 0x3c) >> 2); if (value4 != -1) { byte3 = ((value3 & 0x03) << 6) | (value4); } else { byte3 = null; } } else { byte2 = null; byte3 = null; } this.appendByte(byte1); this.appendByte(byte2); this.appendByte(byte3); i += 4; } return this; }, //------------------------------------------------------------------------- 'toBase64String': function() { var result; var length; var i; var byte1, byte2, byte3; var char1, char2, char3, char4; i = 0; length = this.length(); result = new Array(Math.ceil(length/3)); while (i < length) { byte1 = this.byteAtIndex(i); if ((i+2) < length) { byte2 = this.byteAtIndex(i+1); byte3 = this.byteAtIndex(i+2); } else if ((i+2) == length) { byte2 = this.byteAtIndex(i+1); byte3 = null; } else { byte2 = null; byte3 = null; } char1 = this.base64mapIndex[byte1 >> 2]; if (byte2 != null) { char2 = this.base64mapIndex[((byte1 & 0x03) << 4) | ((byte2 & 0xf0) >> 4)]; if (byte3 != null) { char3 = this.base64mapIndex[((byte2 & 0x0f) << 2) | ((byte3 & 0xc0) >> 6)]; char4 = this.base64mapIndex[(byte3 & 0x3f)]; } else { char3 = this.base64mapIndex[(byte2 & 0x0f) << 2]; char4 = "="; } } else { char2 = this.base64mapIndex[(byte1 & 0x03) << 4]; char3 = "="; char4 = "="; } result.push(char1 + char2 + char3 + char4); i += 3; } return result.join(""); }, //------------------------------------------------------------------------- 'base32map': "0123456789abcdefghjkmnpqrstvwxyz", 'base32mapIndex': "0123456789abcdefghjkmnpqrstvwxyz".split(''), //------------------------------------------------------------------------- 'appendBase32String': function(aValue) { var value; var i; var length; var value1, value2, value3, value4, value5, value6, value7, value8; var byte1, byte2, byte3, byte4, byte5; value = aValue.toLowerCase(); value = value.replace(/[\s\-]/g, ''); value = value.replace(/[0o]/g, '0'); value = value.replace(/[1il]/g, '1'); length = value.length; if ((length % 8) != 0) { MochiKit.Logging.logError("the value passed to the 'ByteArray.setBase32Value' is not correct"); throw Clipperz.ByteArray.exception.InvalidValue; } i = 0; while (i> 2); if (value3 != -1) { byte2 = ((value2 & 0x03) << 6) | (value3 << 1) | ((value4 & 0x10) >> 4); if (value5 != -1) { byte3 = ((value4 & 0x0f) << 4) | ((value5 & 0x1e) >> 1); if (value6 != -1) { byte4 = ((value5 & 0x01) << 7) | (value6 << 2) | ((value7 & 0x18) >> 3); if (value8 != -1) { byte5 = ((value7 & 0x07) << 5) | (value8); } } } } this.appendByte(byte1); this.appendByte(byte2); this.appendByte(byte3); this.appendByte(byte4); this.appendByte(byte5); i += 8; } return this; }, //------------------------------------------------------------------------- 'toBase32String': function() { var result; var length; var i; var byte1, byte2, byte3, byte4, byte5; var char1, char2, char3, char4, char5, char6, char7, char8; i = 0; length = this.length(); result = new Array(Math.ceil(length/5)); while (i < length) { byte1 = this.byteAtIndex(i); if ((i+4) < length) { byte2 = this.byteAtIndex(i+1); byte3 = this.byteAtIndex(i+2); byte4 = this.byteAtIndex(i+3); byte5 = this.byteAtIndex(i+4); } else if ((i+4) == length) { byte2 = this.byteAtIndex(i+1); byte3 = this.byteAtIndex(i+2); byte4 = this.byteAtIndex(i+3); byte5 = null; } else if ((i+3) == length) { byte2 = this.byteAtIndex(i+1); byte3 = this.byteAtIndex(i+2); byte4 = null; byte5 = null; } else if ((i+2) == length) { byte2 = this.byteAtIndex(i+1); byte3 = null; byte4 = null; byte5 = null; } else { byte2 = null; byte3 = null; byte4 = null; byte5 = null; } char1 = this.base32mapIndex[byte1 >> 3]; char2 = char3 = char4 = char5 = char6 = char7 = char8 = "="; if (byte2 != null) { char2 = this.base32mapIndex[((byte1 & 0x07) << 2) | ((byte2 & 0xc0) >> 6)]; char3 = this.base32mapIndex[((byte2 & 0x3e) >> 1)]; if (byte3 != null) { char4 = this.base32mapIndex[((byte2 & 0x01) << 4) | ((byte3 & 0xf0) >> 4)]; if (byte4 != null) { char5 = this.base32mapIndex[((byte3 & 0x0f) << 1) | ((byte4 & 0x80) >> 7)]; char6 = this.base32mapIndex[(byte4 & 0x7c) >> 2]; if (byte5 != null) { char7 = this.base32mapIndex[((byte4 & 0x03) << 3) | ((byte5 & 0xe0) >> 5)]; char8 = this.base32mapIndex[(byte5 & 0x1f)]; } else { char7 = this.base32mapIndex[(byte4 & 0x03) << 3]; } } else { char5 = this.base32mapIndex[(byte3 & 0x0f) << 1]; } } else { char4 = this.base32mapIndex[(byte2 & 0x01) << 4]; } } else { char2 = this.base32mapIndex[(byte1 & 0x07) << 2]; } result.push(char1 + char2 + char3 + char4 + char5 + char6 + char7 + char8); i += 5; } return result.join(""); }, //------------------------------------------------------------------------- 'split': function(aStartingIndex, anEndingIndex) { throw Clipperz.Base.exception.AbstractMethod; }, //------------------------------------------------------------------------- 'increment': function() { var i; var done; done = false; i = this.length() - 1; while ((i>=0) && (done == false)) { var currentByteValue; currentByteValue = this.byteAtIndex(i); if (currentByteValue == 0xff) { this.setByteAtIndex(0, i); if (i>= 0) { i --; } else { done = true; } } else { this.setByteAtIndex(currentByteValue + 1, i); done = true; } } }, //------------------------------------------------------------------------- 'arrayValues': function() { throw Clipperz.Base.exception.AbstractMethod; }, //------------------------------------------------------------------------- __syntaxFix__: "syntax fix" }); //============================================================================= // // Clipperz.ByteArray_hex // //============================================================================= Clipperz.ByteArray_hex = function (args) { this._value = ""; if (typeof(args) != 'undefined') { if (args.constructor == Array) { this.appendBytes(args); } else if (args.constructor == String) { if (args.indexOf("0x") == 0) { var value; value = args.substring(2).toLowerCase(); if (/[0123456789abcdef]*/.test(value)) { if ((value.length % 2) == 0) { this._value = value; } else { this._value = "0" + value; } } else { MochiKit.Logging.logError("Clipperz.ByteArray should be inizialized with an hex string."); throw Clipperz.ByteArray.exception.InvalidValue; } } else { var value; var i,c; c = args.length; value = new Array(c); for (i=0; i 0xxxxxxx result.push(unicode); // } else if ((unicode >= 0x80) && (unicode <= 0x7ff)) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx } else if (unicode <= 0x7ff) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx result.push((unicode >> 6) | 0xc0); result.push((unicode & 0x3F) | 0x80); // } else if ((unicode >= 0x0800) && (unicode <= 0xffff)) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx } else if (unicode <= 0xffff) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx result.push((unicode >> 12) | 0xe0); result.push(((unicode >> 6) & 0x3f) | 0x80); result.push((unicode & 0x3f) | 0x80); } else { // 0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx result.push((unicode >> 18) | 0xf0); result.push(((unicode >> 12) & 0x3f) | 0x80); result.push(((unicode >> 6) & 0x3f) | 0x80); result.push((unicode & 0x3f) | 0x80); } } } this._value = result; } else { this._value = []; this.appendBytes(MochiKit.Base.extend(null, arguments)); } } else { this._value = []; } return this; } Clipperz.ByteArray_array.prototype = MochiKit.Base.update(new Clipperz.ByteArray_abstract(), { //------------------------------------------------------------------------- 'toString': function() { return "Clipperz.ByteArray_array"; }, //------------------------------------------------------------------------- 'clone': function() { var result; result = this.newInstance(); result.appendBytes(this._value); return result; }, //------------------------------------------------------------------------- 'newInstance': function() { return new Clipperz.ByteArray_array(); }, //------------------------------------------------------------------------- 'reset': function() { this._value = []; }, //------------------------------------------------------------------------- 'length': function() { return (this._value.length); }, //------------------------------------------------------------------------- 'appendBlock': function(aBlock) { MochiKit.Base.extend(this._value, aBlock._value); return this; }, //------------------------------------------------------------------------- 'appendByte': function(aValue) { if (aValue != null) { this.checkValue(aValue); this._value.push(aValue); } return this; }, //------------------------------------------------------------------------- 'byteAtIndex': function(anIndex) { return this._value[anIndex]; }, 'setByteAtIndex': function(aValue, anIndex) { var missingBytes; this.checkValue(aValue); missingBytes = anIndex - this.length(); if (missingBytes < 0) { this._value[anIndex] = aValue; } else if (missingBytes == 0) { this._value.push(aValue); } else { var i,c; c = missingBytes; for (i=0; i 0xxxxxxx result = self.byteToHex(aUnicode); // } else if ((aUnicode >= 0x80) && (aUnicode <= 0x7ff)) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx } else if (aUnicode <= 0x7ff) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx result = self.byteToHex((aUnicode >> 6) | 0xc0); result += self.byteToHex((aUnicode & 0x3F) | 0x80); // } else if ((aUnicode >= 0x0800) && (aUnicode <= 0xffff)) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx } else if (aUnicode <= 0xffff) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx result = self.byteToHex((aUnicode >> 12) | 0xe0); result += self.byteToHex(((aUnicode >> 6) & 0x3f) | 0x80); result += self.byteToHex((aUnicode & 0x3f) | 0x80); } else { // 0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx result = self.byteToHex((aUnicode >> 18) | 0xf0); result += self.byteToHex(((aUnicode >> 12) & 0x3f) | 0x80); result += self.byteToHex(((aUnicode >> 6) & 0x3f) | 0x80); result += self.byteToHex((aUnicode & 0x3f) | 0x80); } return result; } Clipperz.ByteArray.pushUtf8BytesOfUnicodeChar = function(anArray, aUnicode) { var self; self = Clipperz.ByteArray; if (aUnicode <= 0x7f) { // 0x00000000 - 0x0000007f -> 0xxxxxxx anArray.push(aUnicode); // } else if ((aUnicode >= 0x80) && (aUnicode <= 0x7ff)) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx } else if (aUnicode <= 0x7ff) { // 0x00000080 - 0x000007ff -> 110xxxxx 10xxxxxx anArray.push((aUnicode >> 6) | 0xc0); anArray.push((aUnicode & 0x3F) | 0x80); // } else if ((aUnicode >= 0x0800) && (aUnicode <= 0xffff)) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx } else if (aUnicode <= 0xffff) { // 0x00000800 - 0x0000ffff -> 1110xxxx 10xxxxxx 10xxxxxx anArray.push((aUnicode >> 12) | 0xe0); anArray.push(((aUnicode >> 6) & 0x3f) | 0x80); anArray.push((aUnicode & 0x3f) | 0x80); } else { // 0x00010000 - 0x001fffff -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx anArray.push((aUnicode >> 18) | 0xf0); anArray.push(((aUnicode >> 12) & 0x3f) | 0x80); anArray.push(((aUnicode >> 6) & 0x3f) | 0x80); anArray.push((aUnicode & 0x3f) | 0x80); } } Clipperz.ByteArray.exception = { InvalidValue: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue") }; //############################################################################# Clipperz.ByteArrayIterator = function(args) { args = args || {}; this._byteArray = args.byteArray; this._blockSize = args.blockSize; this._finalPadding = args.finalPadding || false; this._currentPosition = 0; return this; } Clipperz.ByteArrayIterator.prototype = MochiKit.Base.update(null, { //------------------------------------------------------------------------- 'toString': function() { return "Clipperz.ByteArrayIterator"; }, //------------------------------------------------------------------------- 'blockSize': function() { var result; result = this._blockSize; return result; }, //------------------------------------------------------------------------- 'currentPosition': function() { var result; result = this._currentPosition; return result; }, //------------------------------------------------------------------------- 'byteArray': function() { var result; result = this._byteArray; return result; }, //------------------------------------------------------------------------- 'finalPadding': function() { var result; result = this._finalPadding; return result; }, //------------------------------------------------------------------------- 'nextBlock': function() { var result; var currentPosition; var byteArrayLength; currentPosition = this._currentPosition; byteArrayLength = this.byteArray().length(); if (currentPosition < byteArrayLength) { var i,c; c = this.blockSize(); result = new Array(c); for (i=0; i