Socket
Socket
Sign inDemoInstall

@xoi/gps-metadata-remover

Package Overview
Dependencies
79
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.10 to 1.1.0

4

CHANGES.md

@@ -0,1 +1,5 @@

# 1.1.0
- Removes logs from production builds
- Makes removal of XMP metadata optional
# 1.0.10

@@ -2,0 +6,0 @@

3

lib/gpsRemoverHelpers.js

@@ -14,7 +14,6 @@ "use strict";

const dataBuffer = await read(size, offset);
console.log('next chunk', dataBuffer); // eslint-disable-next-line no-await-in-loop
// eslint-disable-next-line no-await-in-loop
// const decodedData = await base64.atob(currentTagInfoChunk)
// const dataBuffer = binaryStringToArrayBuffer(decodedData)
// eslint-disable-next-line new-cap
return new _jdataview.default(dataBuffer, 0, dataBuffer.byteLength);

@@ -21,0 +20,0 @@ };

@@ -27,3 +27,2 @@ "use strict";

console.log('writing 0s on gps data...', entries, entryOffset);
const bytesToWipe = entries * 12;

@@ -35,3 +34,2 @@ const encodedWipeoutString = await (0, _gpsRemoverHelpers.getEncodedWipeoutString)(bytesToWipe);

const readTag = async (offset, littleEndian, read) => {
console.log('preparing to read tag');
const tagDataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(12, offset, read);

@@ -42,3 +40,2 @@ const tag = tagDataView.getUint16(0, littleEndian);

const valueOffset = tagDataView.getUint32(8, littleEndian);
console.log('read tag', tag, type, numValues, valueOffset);
return {

@@ -60,3 +57,2 @@ tag,

const tagsOffset = startOffset + 2;
console.log('# of exif entries', entries);

@@ -67,3 +63,2 @@ for (let i = 0; i < entries; i++) {

if (currentTag.tag === GPS_EXIF_TAG && currentTag.type === 4 && currentTag.numValues === 1) {
console.log('gps tag found', startOffset, currentTag.valueOffset);
return currentTag.valueOffset;

@@ -88,5 +83,3 @@ }

const findGPSinExifJpg = async (exifDataView, size, masterOffset, read, write) => {
console.log('exifDataView', exifDataView, size);
const littleEndian = isLittleEndian(exifDataView);
console.log('isLittleEndian?', littleEndian, exifDataView.getUint32(0));
const gpsOffset = await findGPSTagInTags(masterOffset + 8, littleEndian, read);

@@ -102,3 +95,3 @@

const imageGpsExifRemoverSkip = async (read, write) => {
const imageGpsExifRemoverSkip = async (read, write, skipXMPRemoval) => {
const fileTypeDataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(4, 0, read);

@@ -110,3 +103,2 @@ const fileTypeTag = fileTypeDataView.getUint32(0);

if (fileTypeTag === PNG_TAG) {
console.log('png identified');
offset += 8;

@@ -118,15 +110,10 @@ let pngCurrentTagSize = 0;

const pngTagDataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(8, offset, read);
console.log('png tag data view', pngTagDataView, offset);
pngCurrentTagSize = pngTagDataView.getUint32(0);
pngCurrentTag = pngTagDataView.getUint32(4);
console.log('current png tag', pngCurrentTagSize, pngCurrentTag);
if (pngCurrentTag === EXIF_ASCII_TAG_PNG) {
console.log('found exif in png');
const offsetOfExifData = offset + 8;
const exifDataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(pngCurrentTagSize, offsetOfExifData, read);
console.log('png exif view', exifDataView);
removedGps = await findGPSinExifJpg(exifDataView, pngCurrentTagSize, offsetOfExifData, read, write);
} else if (pngCurrentTag === PNG_ITXT_TAG) {
console.log('found itxt in png');
} else if (pngCurrentTag === PNG_ITXT_TAG && !skipXMPRemoval) {
const offsetOfPotentialXMPTag = offset + 8;

@@ -139,3 +126,2 @@

if (potentialXMPTag === PNG_XMP_TAG) {
console.log('wiping png XMP metadata');
const wipeoutString = (0, _gpsRemoverHelpers.getWipeoutString)(pngCurrentTagSize);

@@ -154,3 +140,2 @@ await write(wipeoutString, offsetOfPotentialXMPTag, 'ascii');

} else if (fileTypeTag === JPEG_TAG_EXIF || fileTypeTag === JPEG_TAG_JFIF) {
console.log('jpg identified - exif or jfif');
offset += 4;

@@ -177,4 +162,3 @@

if (exifTag === EXIF_ASCII_TAG_JPEG) {
console.log('sanity checked and confirmed presence of exif', offset); // 2 byte size + 4 byte 'Exif' + 2 empty bytes
// 2 byte size + 4 byte 'Exif' + 2 empty bytes
offset += 8;

@@ -188,5 +172,3 @@ const exifDataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(sizeOfExifData, offset, read);

const tiffExifOffsetDataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(4, offset, read);
console.log('tiff data view', tiffExifOffsetDataView);
const tiffExifOffset = tiffExifOffsetDataView.getUint32(0, littleEndian);
console.log('tiff exif offset', tiffExifOffset);
offset = tiffExifOffset;

@@ -193,0 +175,0 @@ removedGps = await findGPSinExifTiff(offset, read, write, littleEndian);

@@ -20,5 +20,12 @@ "use strict";

const removeLocation = async (photoUri, read, write) => {
const removeLocation = async (photoUri, read, write, options = {}) => {
const optionsWithDefaults = {
skipXMPRemoval: false,
...options
};
const {
skipXMPRemoval
} = optionsWithDefaults;
const preparedUri = removeFileSlashPrefix(photoUri);
return isVideo(preparedUri) ? await (0, _videoGpsMetadataRemover.videoGpsMetadataRemoverSkip)(read, write) : await (0, _imageGpsExifRemover.imageGpsExifRemoverSkip)(read, write);
return isVideo(preparedUri) ? await (0, _videoGpsMetadataRemover.videoGpsMetadataRemoverSkip)(read, write, skipXMPRemoval) : await (0, _imageGpsExifRemover.imageGpsExifRemoverSkip)(read, write, skipXMPRemoval);
};

@@ -25,0 +32,0 @@

@@ -25,3 +25,2 @@ "use strict";

const dataToWipe = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(sizeToRemove, offset, read);
console.log('data to wipe', dataToWipe.getString(sizeToRemove, 0));

@@ -36,4 +35,3 @@ if (suppliedWipeoutString === '') {

const videoGpsMetadataRemoverSkip = async (read, write) => {
console.log('preparing to read video skip...');
const videoGpsMetadataRemoverSkip = async (read, write, skipXMPRemoval) => {
let gpsTagFound = false;

@@ -45,7 +43,4 @@ let stopSearching = false; // eslint-disable-next-line new-cap

while (!stopSearching && !gpsTagFound) {
console.log('reading next tag in video...');
const dataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(8, offset, read); // an atom must have a length of at least 8
console.log('tag bite + length', dataView.buffer, dataView.byteLength);
if (dataView.byteLength === 0) {

@@ -59,3 +54,2 @@ stopSearching = true;

const tagName = dataView.getString(4, 4);
console.log('found tag', tagName, tagLength);

@@ -68,5 +62,3 @@ if (tagLength === 0) {

if (tagName === META_ATOM_TAG) {
console.log('found meta tag in video', tagLength);
const metaTagDataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(tagLength, offset, read);
console.log('meta buffer', metaTagDataView);
const metaBaseOffset = 0;

@@ -84,3 +76,2 @@ const hdlrSize = metaTagDataView.getUint32(metaBaseOffset + 8);

const currentKeyName = metaTagDataView.getString(currentKeySize - 8, currentKeyOffset + 8);
console.log('finding keys', currentKeyName, currentKeySize);

@@ -113,14 +104,11 @@ if (currentKeyName === TAG_TO_STRIP) {

} else {
console.log('no gps in this metadata...'); // no gps in the metadata
// no gps in the metadata
offset += tagLength;
}
} else if (TAGS_TO_ENTER.includes(tagName)) {
console.log('moov or udta tag found');
offset += 8;
} else if (tagName === UUID_TAG || tagName === XMP_TAG) {
} else if ((tagName === UUID_TAG || tagName === XMP_TAG) && !skipXMPRemoval) {
// XMP is an alternative tag format pushed by adobe that can have gps
// (can also be id'd by UUID atom)
// we just want to wipe it
console.log('found uuid tag');
gpsTagFound = true;

@@ -131,6 +119,4 @@ await wipeData(tagLength - 8, offset + 8, write, read);

// ©xyz is an alternative gps tag format that some android phones use
console.log('found xyz tag');
const xyzDataView = await (0, _gpsRemoverHelpers.readNextChunkIntoDataView)(tagLength, offset, read);
const xyzString = xyzDataView.getString(tagLength, 0);
console.log('xyz data', xyzString);
const plusIndex = xyzString.indexOf('+');

@@ -142,3 +128,2 @@ const slashIndex = xyzString.indexOf('/');

const wipeoutString = dataString.replace(/[0-9]/g, "0");
console.log('xyz wipeout string', dataString, wipeoutString);
await wipeData(wipeoutString.length, offset + plusIndex, write, read, wipeoutString); //await wipeData(dashIndex - plusIndex - 1, offset + plusIndex, write, read)

@@ -149,3 +134,2 @@ //await wipeData(slashIndex - dashIndex - 1, offset + dashIndex, write, read)

} else {
console.log('xyz data was malformed, skipping');
offset += tagLength;

@@ -161,3 +145,2 @@ } // 10 = 8 byte tag lenght + tag, 2 byte internal length of xyz data

console.log('exiting video skip remover');
return gpsTagFound;

@@ -164,0 +147,0 @@ };

{
"name": "@xoi/gps-metadata-remover",
"version": "1.0.10",
"version": "1.1.0",
"description": "Removes GPS metadata from images and videos",

@@ -33,2 +33,3 @@ "repository": {

"@babel/preset-flow": "^7.11.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"flow-bin": "^0.109.0",

@@ -35,0 +36,0 @@ "flow-copy-source": "^2.0.9",

@@ -46,2 +46,16 @@ # `@xoi/gps-metadata-remover`

#### XMP Removal
One of the metadata formats from which this package removes metadata is Adobe's [XMP](https://www.adobe.com/products/xmp.html).
Currently, if it finds XMP metadata in a file, this package simply wipes the whole of the XMP block rather than just the GPS metadata in that block; this code was originally written under a bit of a time crunch and removing all of the XMP was acceptable since we don't use XMP at all.
If you need to leave XMP intact, pass the optional `options` parameter object to `removeLocation` with `skipXMPRemoval` set to `true`:
```javascript
const gpsWasRemoved = await removeLocation(destPath, read, write, { skipXMPRemoval })
```
At some point I'll write (or accept a PR for) the logic to properly find and remove just the GPS from XMP and leave the rest.
## Testing

@@ -48,0 +62,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc