Comparing version 0.1.0 to 1.0.0
{ | ||
"name": "uue", | ||
"main": "uue.js", | ||
"version": "0.1.0", | ||
"version": "1.0.0", | ||
"description": "UUE decoder and encoder for Node.js", | ||
"keywords": ["UUE", "uuencode", "uudecode", "uuencoding", "uudecoding"], | ||
"keywords": ["uue", "uuencode", "uudecode", "uuencoding", "uudecoding"], | ||
"author": { "name": "Mithgol the Webmaster" }, | ||
@@ -8,0 +8,0 @@ "repository": { |
@@ -1,4 +0,4 @@ | ||
The **UUE** module is able to perform [uuencoding](http://en.wikipedia.org/wiki/Uuencoding) of a file (or Node.js Buffer) to a text message. | ||
The **UUE** module is able to perform [uuencoding](http://en.wikipedia.org/wiki/Uuencoding) of a file (or Node.js Buffer) to a text message. This module is also able to find and decode uuencoded files in text messages. | ||
The module is named after a common `.UUE` suffix for Fidonet echomail areas spreading uuencoded files (sometimes the results of such encoding are also known as “UUE codes”). | ||
The module is named after a common `.UUE` suffix for Fidonet echomail areas where uuencoded files are posted (sometimes the results of such encoding are also known as “UUE codes”). | ||
@@ -21,3 +21,3 @@ The module is written in JavaScript and requires [Node.js](http://nodejs.org/) to run. | ||
When you `require()` the installed module, you get an object that has the following method: | ||
When you `require()` the installed module, you get an object that has the following methods: | ||
@@ -32,2 +32,4 @@ ### encode(encodeSource, encodeOptions) | ||
**Note: ** if a file's name is given to the `.encode` method, a synchronous reading of the given file is performed. If you need an asynchronous reading, perform it yourself and give the resulting Buffer to the `.encode` method. | ||
The optional `encodeOptions` parameter is an object with the following optional properties: | ||
@@ -41,5 +43,23 @@ | ||
Example (uuencoding the word `'Cat'`, [as in Wikipedia):](http://en.wikipedia.org/w/index.php?title=Uuencoding&oldid=607304984#Formatting_mechanism) | ||
![(uuencoding example)](https://cloud.githubusercontent.com/assets/1088720/3140039/8953db68-e901-11e3-9759-0ebff59ea331.gif) | ||
### decodeFile(text, filename) | ||
Using the given `filename`, finds the uuencoded file in the given `text`, decodes the file and returns it as a Node.js [Buffer.](http://nodejs.org/docs/latest/api/buffer.html) | ||
Lines in the given `text` are expected to be separated by `'\n'` (`\x0A`). | ||
Invalid UUE codes are ignored. | ||
Any UUE codes of any file that has a different filename (not the given `filename`) are ignored. (If `text` contains several uuencoded files, it is not necessary for `filename` to go first.) | ||
If several uuencoded files have the same `filename`, only the first is returned. | ||
If the file cannot be found, `null` is returned. | ||
## Locking files | ||
The module **does not** lock any files and **does not** create any “lock files” (flag files, semaphore files). The module's caller should control the access to the file being encoded. | ||
The module **does not** lock any files and **does not** create any “lock files” (flag files, semaphore files). The module's caller should control the access to the file that is being encoded. | ||
@@ -46,0 +66,0 @@ ## Testing the UUE module |
125
uue.js
@@ -55,15 +55,15 @@ var fs = require('fs'); | ||
while( offset < encodeSource.length ){ | ||
var triplet, byte1, byte2, byte3, total, charCode; | ||
var triplet, total, charCode; | ||
if( encodeSource.length - offset >= 45 ){ // complete line, 15 triplets | ||
output.push(String.fromCharCode(45 + 32)); | ||
for( triplet = 0; triplet < 15; triplet++ ){ | ||
byte1 = encodeSource.readUInt8(offset); | ||
total = 0; | ||
total += encodeSource.readUInt8(offset) << 16; | ||
offset++; | ||
byte2 = encodeSource.readUInt8(offset); | ||
total += encodeSource.readUInt8(offset) << 8; | ||
offset++; | ||
byte3 = encodeSource.readUInt8(offset); | ||
total += encodeSource.readUInt8(offset); | ||
offset++; | ||
total = (byte1 << 16) + (byte2 << 8) + byte3; | ||
charCode = total >>> 18; | ||
@@ -89,11 +89,11 @@ if( charCode === 0 ) charCode = 64; | ||
for( triplet = 0; triplet < tripletNum; triplet++ ){ | ||
byte1 = encodeSource.readUInt8(offset); | ||
total = 0; | ||
total += encodeSource.readUInt8(offset) << 16; | ||
offset++; | ||
byte2 = encodeSource.readUInt8(offset); | ||
total += encodeSource.readUInt8(offset) << 8; | ||
offset++; | ||
byte3 = encodeSource.readUInt8(offset); | ||
total += encodeSource.readUInt8(offset); | ||
offset++; | ||
total = (byte1 << 16) + (byte2 << 8) + byte3; | ||
charCode = total >>> 18; | ||
@@ -116,15 +116,15 @@ if( charCode === 0 ) charCode = 64; | ||
if( offset < encodeSource.length ){ // some bytes remain | ||
byte1 = encodeSource.readUInt8(offset); | ||
total = 0; | ||
total += encodeSource.readUInt8(offset) << 16; | ||
offset++; | ||
if( offset < encodeSource.length ){ | ||
byte2 = encodeSource.readUInt8(offset); | ||
total += encodeSource.readUInt8(offset) << 8; | ||
offset++; | ||
} else byte2 = 0; | ||
} | ||
if( offset < encodeSource.length ){ | ||
byte3 = encodeSource.readUInt8(offset); | ||
total += encodeSource.readUInt8(offset); | ||
offset++; | ||
} else byte3 = 0; | ||
} | ||
total = (byte1 << 16) + (byte2 << 8) + byte3; | ||
charCode = total >>> 18; | ||
@@ -156,2 +156,91 @@ if( charCode === 0 ) charCode = 64; | ||
UUE.prototype.decodeFile = function(text, filename){ | ||
var matches = []; | ||
var potentialUUE = RegExp( | ||
[ | ||
'^begin [0-7]{3} ' + filename + '\n', | ||
'(', | ||
'(?:[\x20-\x60]+\n)*', // allow garbage after significant characters | ||
')', | ||
'`\n', | ||
'end$' | ||
].join(''), | ||
'gm' | ||
); | ||
var continueSearch = true; | ||
do { | ||
var nextMatch = potentialUUE.exec(text); | ||
if( nextMatch === null ){ | ||
continueSearch = false; | ||
} else { | ||
matches.push(nextMatch); | ||
} | ||
} while( continueSearch ); | ||
if( matches.length === 0 ) return null; | ||
var fileFound = null; | ||
matches.forEach(function(nextMatch){ | ||
if( fileFound !== null ) return; | ||
if( nextMatch[1].length < 1 ){ | ||
fileFound = new Buffer(0); | ||
return; | ||
} | ||
var decodingError = false; | ||
var decoded = nextMatch[1].split('\n'); | ||
decoded.pop(); // cut last \n (it is not a separator) | ||
decoded = decoded.map(function(lineUUE){ | ||
/* jshint bitwise:false */ | ||
if( decodingError ) return null; | ||
var byteLength = (lineUUE.charCodeAt(0) - 32) % 64; | ||
if( byteLength === 0 ) return new Buffer(0); | ||
var charLength = ( (byteLength / 3) |0 ) * 4; | ||
if( byteLength % 3 !== 0 ) charLength += 4; | ||
if( 1 + charLength > lineUUE.length ){ | ||
decodingError = true; | ||
return null; | ||
} | ||
var targetBuffer = new Buffer(byteLength); | ||
var step, total; | ||
var stringOffset = 1; | ||
var bufferOffset = 0; | ||
for( step = 0; step < ( (charLength / 4) |0 ); step++ ){ | ||
total = 0; | ||
total += ((lineUUE.charCodeAt(stringOffset) - 32) % 64) << 18; | ||
stringOffset++; | ||
total += ((lineUUE.charCodeAt(stringOffset) - 32) % 64) << 12; | ||
stringOffset++; | ||
total += ((lineUUE.charCodeAt(stringOffset) - 32) % 64) << 6; | ||
stringOffset++; | ||
total += (lineUUE.charCodeAt(stringOffset) - 32) % 64; | ||
stringOffset++; | ||
// noAssert === true: | ||
// silently apply &0xFF mask, silently drop after byteLength | ||
targetBuffer.writeUInt8( total >>> 16, bufferOffset, true ); | ||
bufferOffset++; | ||
targetBuffer.writeUInt8( total >>> 8, bufferOffset, true ); | ||
bufferOffset++; | ||
targetBuffer.writeUInt8( total, bufferOffset, true ); | ||
bufferOffset++; | ||
} | ||
return targetBuffer; | ||
}); | ||
if( decodingError ) return; | ||
// now `decoded` is a valid array containing buffers, | ||
// because `null` could appear only in `decodingError` state | ||
fileFound = Buffer.concat(decoded); | ||
}); | ||
return fileFound; | ||
}; | ||
UUE.prototype.errors = { | ||
@@ -158,0 +247,0 @@ UNKNOWN_SOURCE_TYPE: "The source's type is unknown!" |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
16188
205
1
79