You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 7-8.RSVP
Socket
Socket
Sign inDemoInstall

exif

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.0 to 0.2.0

lib/exif/makernotes/agfa.js

30

lib/exif/Buffer.js

@@ -7,27 +7,27 @@ //

return this[offset];
}
};
Buffer.prototype.getSignedByte = function (offset) {
return (this[offset] > 127) ? this[offset] - 256 : this[offset];
}
};
Buffer.prototype.getShort = function (offset, bigEndian) {
var short = (bigEndian) ? (this[offset] << 8) + this[offset + 1] : (this[offset + 1] << 8) + this[offset];
return (short < 0) ? short + 65536 : short;
}
var shortVal = (bigEndian) ? (this[offset] << 8) + this[offset + 1] : (this[offset + 1] << 8) + this[offset];
return (shortVal < 0) ? shortVal + 65536 : shortVal;
};
Buffer.prototype.getSignedShort = function (offset, bigEndian) {
var short = (bigEndian) ? (this[offset] << 8) + this[offset + 1] : (this[offset + 1] << 8) + this[offset];
return (short > 32767) ? short - 65536 : short;
}
var shortVal = (bigEndian) ? (this[offset] << 8) + this[offset + 1] : (this[offset + 1] << 8) + this[offset];
return (shortVal > 32767) ? shortVal - 65536 : shortVal;
};
Buffer.prototype.getLong = function (offset, bigEndian) {
var long = (bigEndian) ? (((((this[offset] << 8) + this[offset + 1]) << 8) + this[offset + 2]) << 8) + this[offset + 3] : (((((this[offset + 3] << 8) + this[offset + 2]) << 8) + this[offset + 1]) << 8) + this[offset];
return (long < 0) ? long + 4294967296 : long;
}
var longVal = (bigEndian) ? (((((this[offset] << 8) + this[offset + 1]) << 8) + this[offset + 2]) << 8) + this[offset + 3] : (((((this[offset + 3] << 8) + this[offset + 2]) << 8) + this[offset + 1]) << 8) + this[offset];
return (longVal < 0) ? longVal + 4294967296 : longVal;
};
Buffer.prototype.getSignedLong = function (offset, bigEndian) {
var long = (bigEndian) ? (((((this[offset] << 8) + this[offset + 1]) << 8) + this[offset + 2]) << 8) + this[offset + 3] : (((((this[offset + 3] << 8) + this[offset + 2]) << 8) + this[offset + 1]) << 8) + this[offset];
return (long > 2147483647) ? long - 4294967296 : long;
}
var longVal = (bigEndian) ? (((((this[offset] << 8) + this[offset + 1]) << 8) + this[offset + 2]) << 8) + this[offset + 3] : (((((this[offset + 3] << 8) + this[offset + 2]) << 8) + this[offset + 1]) << 8) + this[offset];
return (longVal > 2147483647) ? longVal - 4294967296 : longVal;
};

@@ -39,2 +39,2 @@ Buffer.prototype.getString = function (offset, length) {

return string.join('');
}
};

@@ -31,7 +31,7 @@ var fs = require('fs'),

image : [], // Information about the main image
thumbnail : [], // Information about the thumbnail
thumbnail : [], // Information about the thumbnail
exif : [], // Exif information
gps : [], // GPS information
interoperability: [], // Exif Interoperability information
makernote : null // Makernote information (n/a yet)
gps : [], // GPS information
interoperability: [], // Exif Interoperability information
makernote : [] // Makernote information
};

@@ -66,5 +66,5 @@

rawData = fs.readFile(image, function (error, data) {
fs.readFile(image, function (error, data) {
if (error)
callback({ message : 'Encountered the following error while trying to read given image: '+error });
callback(new Error('Encountered the following error while trying to read given image: '+error));
else

@@ -76,7 +76,7 @@ self.processImage(data, callback);

callback({ message : 'Given image is neither a buffer nor a file, please provide one of these.' });
callback(new Error('Given image is neither a buffer nor a file, please provide one of these.'));
}
}
};

@@ -91,27 +91,34 @@ ExifImage.prototype.processImage = function (data, callback) {

} else {
callback({ message : 'The given image is not a JPEG and thus unsupported right now.' });
callback(new Error('The given image is not a JPEG and thus unsupported right now.'));
return;
}
try {
while (offset < data.length) {
if (data[offset++] != 0xFF) {
callback({ message : 'Invalid marker found at offset '+(--offset)+'. Expected 0xFF but found 0x'+data[offset].toString(16).toUpperCase() });
return;
while (offset < data.length) {
if (data[offset++] != 0xFF) {
callback(new Error('Invalid marker found at offset '+(--offset)+'. Expected 0xFF but found 0x'+data[offset].toString(16).toUpperCase()+"."));
return;
}
if (data[offset++] == 0xE1) {
var exifData = self.extractExifData(data, offset + 2, data.getShort(offset, true) - 2);
callback(false, exifData);
return;
} else {
offset += data.getShort(offset, true);
}
}
if (data[offset++] == 0xE1) {
self.extractExifData(data, offset + 2, data.getShort(offset, true) - 2, callback);
return;
} else {
offset += data.getShort(offset, true);
}
} catch (error) {
callback(error);
}
callback({ message : 'No Exif segment found in the given image' });
callback(new Error('No Exif segment found in the given image.'));
}
};
ExifImage.prototype.extractExifData = function (data, start, length, callback) {
ExifImage.prototype.extractExifData = function (data, start, length) {

@@ -124,4 +131,3 @@ var self = this;

if (data.toString('utf8', start, tiffOffset) != 'Exif\0\0') {
callback({ message : 'The Exif data ist not valid.' });
return;
throw new Error('The Exif data ist not valid.');
}

@@ -136,17 +142,15 @@

} else {
callback({ message : 'Invalid TIFF data! Expected 0x4949 or 0x4D4D at offset '+(tiffOffset)+' but found 0x'+data[tiffOffset].toString(16).toUpperCase()+data[tiffOffset + 1].toString(16).toUpperCase() });
return;
throw new Error('Invalid TIFF data! Expected 0x4949 or 0x4D4D at offset '+(tiffOffset)+' but found 0x'+data[tiffOffset].toString(16).toUpperCase()+data[tiffOffset + 1].toString(16).toUpperCase()+".");
}
// Valid TIFF headers always have 0x002A here
if (data.getShort(tiffOffset + 2, this.isBigEndian) != 0x002A) {
var expected = (this.isBigEndian) ? '0x002A' : '0x2A00';
callback({ message : 'Invalid TIFF data! Expected '+expected+' at offset '+(tiffOffset + 2)+' but found 0x'+data[tiffOffset + 2].toString(16).toUpperCase()+data[tiffOffset + 3].toString(16).toUpperCase() });
return;
}
if (data.getShort(tiffOffset + 2, this.isBigEndian) != 0x002A) {
var expected = (this.isBigEndian) ? '0x002A' : '0x2A00';
throw new Error('Invalid TIFF data! Expected '+expected+' at offset '+(tiffOffset + 2)+' but found 0x'+data[tiffOffset + 2].toString(16).toUpperCase()+data[tiffOffset + 3].toString(16).toUpperCase()+".");
}
/********************************* IFD0 **********************************/
/********************************* IFD0 **********************************/
// Offset to IFD0 which is always followed by two bytes with the amount of
// entries in this IFD
// Offset to IFD0 which is always followed by two bytes with the amount of
// entries in this IFD
ifdOffset = tiffOffset + data.getLong(tiffOffset + 4, this.isBigEndian);

@@ -158,3 +162,3 @@ numberOfEntries = data.getShort(ifdOffset, this.isBigEndian);

for (var i = 0; i < numberOfEntries; i++) {
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, ExifImage.TAGS.tiff);
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, this.isBigEndian, ExifImage.TAGS.tiff);
if (exifEntry) this.exifData.image.push(exifEntry);

@@ -165,7 +169,7 @@ }

// Check if there is an offset for IFD1. If so it is always followed by two
// Check if there is an offset for IFD1. If so it is always followed by two
// bytes with the amount of entries in this IFD, if not there is no IFD1
ifdOffset = tiffOffset + data.getLong(ifdOffset + 2 + (numberOfEntries * 12));
ifdOffset = tiffOffset + data.getLong(ifdOffset + 2 + (numberOfEntries * 12), this.isBigEndian);
if (ifdOffset != 0x00000000) {
numberOfEntries = data.getShort(ifdOffset, true);
numberOfEntries = data.getShort(ifdOffset, this.isBigEndian);

@@ -175,3 +179,3 @@ // Each IFD entry consists of 12 bytes which we loop through and extract

for (var i = 0; i < numberOfEntries; i++) {
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, ExifImage.TAGS.tiff);
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, this.isBigEndian, ExifImage.TAGS.tiff);
if (exifEntry) this.exifData.thumbnail.push(exifEntry);

@@ -193,3 +197,3 @@ }

for (var i = 0; i < numberOfEntries; i++) {
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, ExifImage.TAGS.exif);
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, this.isBigEndian, ExifImage.TAGS.exif);
if (exifEntry) this.exifData.exif.push(exifEntry);

@@ -214,3 +218,3 @@ }

for (var i = 0; i < numberOfEntries; i++) {
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, ExifImage.TAGS.gps);
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, this.isBigEndian, ExifImage.TAGS.gps);
if (exifEntry) this.exifData.gps.push(exifEntry);

@@ -235,3 +239,3 @@ }

for (var i = 0; i < numberOfEntries; i++) {
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset);
var exifEntry = self.extractExifEntry(data, (ifdOffset + 2 + (i * 12)), tiffOffset, this.isBigEndian);
if (exifEntry) this.exifData.interoperability.push(exifEntry);

@@ -246,18 +250,45 @@ }

// Nothing here, yet
// Look for Makernote data in the Exif IFD, check which type of proprietary
// Makernotes the image contains, load the respective functionality and
// start the extraction
for (exifEntry in this.exifData.exif) {
if (this.exifData.exif[exifEntry].tag.getShort(0, this.isBigEndian) == 0x927C) {
// Check the header to see what kind of Makernote we are dealing with
if (this.exifData.exif[exifEntry].value.getString(0, 7) === "OLYMP\x00\x01") {
this.extractMakernotes = require('./makernotes/olympus').extractMakernotes;
} else if (this.exifData.exif[exifEntry].value.getString(0, 7) === "AGFA \x00\x01") {
this.extractMakernotes = require('./makernotes/agfa').extractMakernotes;
} else if (this.exifData.exif[exifEntry].value.getString(0, 8) === "EPSON\x00\x01\x00") {
this.extractMakernotes = require('./makernotes/epson').extractMakernotes;
} else if (this.exifData.exif[exifEntry].value.getString(0, 8) === "FUJIFILM") {
this.extractMakernotes = require('./makernotes/fujifilm').extractMakernotes;
} else {
// Makernotes are available but the format is not recognized so
// an error message is pushed instead, this ain't the best
// solution but should do for now
this.exifData.makernote.push({ error: 'Unable to extract Makernote information as it is in an unrecognized format.' });
break;
}
this.exifData.makernote = this.extractMakernotes(data, this.exifData.exif[exifEntry].valueOffset, tiffOffset);
}
}
callback(false, this.exifData);
return this.exifData;
}
};
ExifImage.prototype.extractExifEntry = function (data, entryOffset, tiffOffset, tags) {
ExifImage.prototype.extractExifEntry = function (data, entryOffset, tiffOffset, isBigEndian, tags) {
var entry = {
tag : data.slice(entryOffset, entryOffset + 2),
format : data.getShort(entryOffset + 2, this.isBigEndian),
components : data.getLong(entryOffset + 4, this.isBigEndian),
value : []
format : data.getShort(entryOffset + 2, isBigEndian),
components : data.getLong(entryOffset + 4, isBigEndian),
valueOffset: null,
value : []
}
entry.tagName = (tags && tags[entry.tag.getShort(0, this.isBigEndian)]) ? tags[entry.tag.getShort(0, this.isBigEndian)] : null;
entry.tagName = (tags && tags[entry.tag.getShort(0, isBigEndian)]) ? tags[entry.tag.getShort(0, isBigEndian)] : null;

@@ -267,57 +298,59 @@ switch (entry.format) {

case 0x0001: // unsigned byte, 1 byte per component
var offset = (entry.components <= 4) ? entryOffset + 8 : data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.valueOffset = (entry.components <= 4) ? entryOffset + 8 : data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
for (var i = 0; i < entry.components; i++)
entry.value.push(data.getByte(offset + i));
entry.value.push(data.getByte(entry.valueOffset + i));
break;
case 0x0002: // ascii strings, 1 byte per component
var offset = (entry.components <= 4) ? entryOffset + 8 : data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.value = data.getString(offset, entry.components - 1);
entry.valueOffset = (entry.components <= 4) ? entryOffset + 8 : data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
entry.value = data.getString(entry.valueOffset, entry.components);
if (entry.value[entry.value.length - 1] === "\u0000") // Trim null terminated strings
entry.value = entry.value.substring(0, entry.value.length - 1);
break;
case 0x0003: // unsigned short, 2 byte per component
var offset = (entry.components <= 2) ? entryOffset + 8 : data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.valueOffset = (entry.components <= 2) ? entryOffset + 8 : data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
for (var i = 0; i < entry.components; i++)
entry.value.push(data.getShort(offset + i * 2, this.isBigEndian));
entry.value.push(data.getShort(entry.valueOffset + i * 2, isBigEndian));
break;
case 0x0004: // unsigned long, 4 byte per component
var offset = (entry.components == 1) ? entryOffset + 8 : data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.valueOffset = (entry.components == 1) ? entryOffset + 8 : data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
for (var i = 0; i < entry.components; i++)
entry.value.push(data.getLong(offset + i * 4, this.isBigEndian));
entry.value.push(data.getLong(entry.valueOffset + i * 4, isBigEndian));
break;
case 0x0005: // unsigned rational, 8 byte per component (4 byte numerator and 4 byte denominator)
var offset = data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.valueOffset = data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
for (var i = 0; i < entry.components; i++)
entry.value.push(data.getLong(offset, this.isBigEndian) / data.getLong(offset + 4, this.isBigEndian));
entry.value.push(data.getLong(entry.valueOffset + i * 8, isBigEndian) / data.getLong(entry.valueOffset + i * 8 + 4, isBigEndian));
break;
case 0x0006: // signed byte, 1 byte per component
var offset = (entry.components <= 4) ? entryOffset + 8 : data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.valueOffset = (entry.components <= 4) ? entryOffset + 8 : data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
for (var i = 0; i < entry.components; i++)
entry.value.push(data.getSignedByte(offset + i));
entry.value.push(data.getSignedByte(entry.valueOffset + i));
break;
case 0x0007: // undefined, 1 byte per component
var offset = (entry.components <= 4) ? entryOffset + 8 : data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.value.push(data.slice(offset, offset + entry.components));
entry.valueOffset = (entry.components <= 4) ? entryOffset + 8 : data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
entry.value.push(data.slice(entry.valueOffset, entry.valueOffset + entry.components));
break;
case 0x0008: // signed short, 2 byte per component
var offset = (entry.components <= 2) ? entryOffset + 8 : data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.valueOffset = (entry.components <= 2) ? entryOffset + 8 : data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
for (var i = 0; i < entry.components; i++)
entry.value.push(data.getSignedShort(offset + i * 2, this.isBigEndian));
entry.value.push(data.getSignedShort(entry.valueOffset + i * 2, isBigEndian));
break;
case 0x0009: // signed long, 4 byte per component
var offset = (entry.components == 1) ? entryOffset + 8 : data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.valueOffset = (entry.components == 1) ? entryOffset + 8 : data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
for (var i = 0; i < entry.components; i++)
entry.value.push(data.getSignedLong(offset + i * 4, this.isBigEndian));
entry.value.push(data.getSignedLong(entry.valueOffset + i * 4, isBigEndian));
break;
case 0x000A: // signed rational, 8 byte per component (4 byte numerator and 4 byte denominator)
var offset = data.getLong(entryOffset + 8, this.isBigEndian) + tiffOffset;
entry.valueOffset = data.getLong(entryOffset + 8, isBigEndian) + tiffOffset;
for (var i = 0; i < entry.components; i++)
entry.value.push(data.getSignedLong(offset, this.isBigEndian) / data.getSignedLong(offset + 4, this.isBigEndian));
entry.value.push(data.getSignedLong(entry.valueOffset + i * 8, isBigEndian) / data.getSignedLong(entry.valueOffset + i * 8 + 4, isBigEndian));
break;

@@ -335,3 +368,3 @@

}
};

@@ -402,3 +435,3 @@ /**

0xA40C : 'SubjectDistanceRange',
0xA420 : 'ImageUniqueID',
0xA420 : 'ImageUniqueID'

@@ -582,3 +615,3 @@ },

0xC65C : 'BestQualityScale',
0xC660 : 'Alias Layer Metadata',
0xC660 : 'Alias Layer Metadata'

@@ -620,6 +653,6 @@ },

0x001D : 'GPSDateStamp',
0x001E : 'GPSDifferential',
0x001E : 'GPSDifferential'
}
}
};
{
"name" : "exif",
"version" : "0.1.0",
"version" : "0.2.0",
"description" : "A node.js library to extract Exif metadata from images.",
"author" : "Daniel Leinich <leinich@gmx.net>",
"keywords" : ["exif", "image", "jpeg", "jpg", "tiff", "makernotes", "gps"],
"main" : "./lib/exif",

@@ -7,0 +8,0 @@ "repository" : {

node-exif
=========
With node-exif you can extract Exif metadata from images (JPEG). Exif is a
With _node-exif_ you can extract Exif metadata from images (JPEG). Exif is a
format used, for example, by digital cameras and scanners to save additional

@@ -24,3 +24,3 @@ information about an image in the image file. This information can be the

Easy. Just require node-exif and throw an image at it. If node-exif is able to
Easy. Just require _node-exif_ and throw an image at it. If _node-exif_ is able to
extract data from the image it does so and returns an object with all the

@@ -27,0 +27,0 @@ information found, if an error occurs you will receive an error message. To

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc