1 /*
  2  * 	Copyright (C) 2012-2013 DFKI GmbH
  3  * 	Deutsches Forschungszentrum fuer Kuenstliche Intelligenz
  4  * 	German Research Center for Artificial Intelligence
  5  * 	http://www.dfki.de
  6  * 
  7  * 	Permission is hereby granted, free of charge, to any person obtaining a 
  8  * 	copy of this software and associated documentation files (the 
  9  * 	"Software"), to deal in the Software without restriction, including 
 10  * 	without limitation the rights to use, copy, modify, merge, publish, 
 11  * 	distribute, sublicense, and/or sell copies of the Software, and to 
 12  * 	permit persons to whom the Software is furnished to do so, subject to 
 13  * 	the following conditions:
 14  * 
 15  * 	The above copyright notice and this permission notice shall be included 
 16  * 	in all copies or substantial portions of the Software.
 17  * 
 18  * 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 19  * 	OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
 20  * 	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
 21  * 	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
 22  * 	CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 23  * 	TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 24  * 	SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 25  */
 26 
 27 
 28 define(['md5'],
 29 	/**
 30 	 * A Utility class for creating / reading checksum (files).<br>
 31 	 * 
 32 	 * @name ChecksumUtils
 33 	 * @class
 34 	 * @memberOf mmir.tools
 35 	 * @static
 36 	 * 
 37 	 * @requires CryptoJS (MD5, see https://code.google.com/p/crypto-js/)
 38 	 */
 39 	function(
 40 		CryptoJS
 41 ){
 42 	
 43 	/** 
 44 	 * @private
 45 	 * @type CryptoJS.MD5
 46 	 * @memberOf ChecksumUtils#
 47 	 */
 48 	var cryptoInstance;
 49 	
 50 	/**
 51 	 * @private
 52 	 * @function
 53 	 * @memberOf ChecksumUtils#
 54 	 */
 55 	var computeChecksum = function(str){
 56 		return ''+cryptoInstance.MD5(str);//<- enforce String-value by using: ''+...
 57 	};
 58 	
 59 	/** 
 60 	 * @private
 61 	 * @type String
 62 	 * @memberOf ChecksumUtils#
 63 	 */
 64 	var digestFileExt = '.checksum.txt';
 65 	/** 
 66 	 * @private
 67 	 * @type String
 68 	 * @memberOf ChecksumUtils#
 69 	 */
 70 	var digestContentSeparator = '\t';
 71 	/** 
 72 	 * @private
 73 	 * @type String
 74 	 * @memberOf ChecksumUtils#
 75 	 */
 76 	var digestContentPostfix = '\r\n';
 77 	
 78 	/** 
 79 	 * @private
 80 	 * @function
 81 	 * @memberOf ChecksumUtils#
 82 	 */
 83 	var createDigestFileContent = function(originalText){
 84 	
 85 		var size = originalText.length;
 86 		var digest = computeChecksum(originalText);
 87 		
 88 		return digest + digestContentSeparator + size + digestContentPostfix;
 89 	};
 90 	
 91 	/** 
 92 	 * @returns {PlainObject} <code>{size: Number, hash: String}</code>
 93 	 * @private
 94 	 * @type String
 95 	 * @memberOf ChecksumUtils#
 96 	 */
 97 	var parseDigestFileContent = function(rawTextContent){
 98 		
 99 		var data = rawTextContent.split(digestContentSeparator);
100 		
101 		return {
102 			size: parseInt(data[1]),
103 			hash: data[0]
104 		};
105 	};
106 	
107 	/** 
108 	 * @returns {Boolean}
109 	 * @private
110 	 * @function
111 	 * @memberOf ChecksumUtils#
112 	 */
113 	var verifyIsSame = function(rawTextContent, referenceHash){
114 		
115 		if(typeof referenceHash === 'string'){
116 			referenceHash = parseDigestFileContent(referenceHash);
117 		}
118 		
119 		var origSize = rawTextContent.length;
120 		
121 		if(origSize === referenceHash.size){
122 			return referenceHash.hash === computeChecksum(rawTextContent);
123 		}
124 	};
125 	
126 	/**
127 	 * @lends ChecksumUtils.prototype
128 	 */
129 	return {
130 		/**
131 		 * Must be called before using checksum-generation:
132 		 * sets/initializes the object/function for checksum generation.
133 		 * 
134 		 * @param {CryptoJS} [cryptoImpl] OPTIONAL
135 		 * 				if omitted, the (global!) variable <code>CryptoJS</code> is used by default.
136 		 * 				This argument should be the CryptoJS object containing the MD5 function/algorithm, i.e. CryptoJS.MD5() must be a function!
137 		 * 
138 		 * @memberOf mmir.tools.ChecksumUtils#
139 		 */
140 		init: function(cryptoImpl){
141 			if(!cryptoImpl){
142 				cryptoImpl = CryptoJS;
143 			}
144 			cryptoInstance = cryptoImpl;
145 			return this;
146 		},
147 		/**
148 		 * Creates the content for a checksum file, containing information about
149 		 * the size and hash-value for the supplied String argument.
150 		 * 
151 		 * The result can be "written as is" to a file.
152 		 * 
153 		 * @function
154 		 * @param {String} originalText
155 		 * 						the "raw" text for which to generate the checksum information
156 		 * 
157 		 * @returns {String} the checksum information as a String (formatted as content of a checksum file)
158 		 * 
159 		 * @memberOf mmir.tools.ChecksumUtils#
160 		 */
161 		createContent: createDigestFileContent,
162 		/**
163 		 * Parses the raw text-content of a checksum file and returns an object
164 		 * with properties:
165 		 * 
166 		 * <code>{ size: INTEGER, hash: STRING }</code>
167 		 * 
168 		 * @function
169 		 * @param {String} rawTextContent
170 		 * 					the raw conent of a checksum file
171 		 * 
172 		 * @returns {PlainObject} an object with the extracted properties from the checksum-data:
173 		 * 				{ size: INTEGER, hash: STRING }
174 		 * 
175 		 * @memberOf mmir.tools.ChecksumUtils#
176 		 */
177 		parseContent: parseDigestFileContent,
178 		/**
179 		 * Check if the length / checksum for a raw text is the same as the checksum-information.
180 		 * 
181 		 * NOTE: The actual checksum for the raw text is only generated & checked, if the size is equal.
182 		 * 
183 		 * @function
184 		 * @param {String} rawTextContent
185 		 * 					the (raw) text/content which should be checked
186 		 * @param {String|PlainObject} referenceHash
187 		 * 					the checksum information to check against: either the 
188 		 * 					raw content (String) of a checksum file, or the parsed
189 		 * 					contents of a checksum file, which is a PlainObject with
190 		 * 					properties:
191 		 * 					{ size: INTEGER, hash: STRING }
192 		 * 
193 		 * @returns {Boolean} 
194 		 * 					<code>true</code> if the raw content matches the hash
195 		 * 
196 		 * @memberOf mmir.tools.ChecksumUtils#
197 		 */
198 		isSame: verifyIsSame,
199 		/**
200 		 * Returns the file extension for checksum-files.
201 		 * 
202 		 * CONST
203 		 * 
204 		 * @function
205 		 * @returns {String} the default file extension for checksum files 
206 		 * 						(including the separating dot, eg. ".checksum.txt")
207 		 * 
208 		 * @memberOf mmir.tools.ChecksumUtils# 
209 		 */
210 		getFileExt: function(){
211 			return digestFileExt;
212 		},
213 		/**
214 		 * The Char used for separating fields within checksum files.
215 		 * 
216 		 * @returns {String} the separator char (TAB)
217 		 * 
218 		 * @memberOf mmir.tools.ChecksumUtils#
219 		 */
220 		getConentSeparator: function(){
221 			return digestContentSeparator;
222 		}
223 	};
224 	
225 });//END: define