Skip to content

Commit

Permalink
corrections
Browse files Browse the repository at this point in the history
  • Loading branch information
galkahana committed Nov 2, 2022
1 parent a526db6 commit a9bf252
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 36 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@


**Update 9/11/2019 Ending Support:**
Hi All, after 6 years I decided to finish supporting HummusJS. You may still use the code as is, with the provided license, however I will not be providing answers, solutions, responses etc.
Hi All, after 6 years I decided to finish supporting HummusJS. You may still use the code as is, with the provided license, however I will not be providing answers, solutions, responses etc.

If you want to continue using HummusJS and are looking for a maintained version you can move to [MuhammaraJS](https://github.com/julianhille/MuhammaraJS) which is a drop in replacement for HummusJS. Thanks [Julianhille](https://github.com/julianhille) for maintaining it.

I'd like to thank everyone who used HummusJS and wish you all the best going forward with your projects.
Gal.



Welcome to HummusJS.
A Fast NodeJS Module for Creating, Parsing an Manipulating PDF Files and Streams.
Documentation is available [here](https://github.com/galkahana/HummusJS/wiki).
Expand Down
11 changes: 4 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hummus",
"version": "1.0.110",
"version": "1.0.111",
"description": "Create, read and modify PDF files and streams",
"homepage": "http://pdfhummus.com/",
"license": "Apache-2.0",
Expand Down Expand Up @@ -28,12 +28,6 @@
"PDFRStreamForBuffer.js",
"PDFWStreamForBuffer.js"
],
"dependencies": {
"node-pre-gyp": "^0.10.0"
},
"bundledDependencies": [
"node-pre-gyp"
],
"devDependencies": {
"aws-sdk": "~2.0.0-rc.15",
"chai": "^3.4.0",
Expand All @@ -49,5 +43,8 @@
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.10"
}
}
20 changes: 14 additions & 6 deletions src/ObjectByteWriterWithPosition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,29 @@ IOBasicTypes::LongBufferSizeType ObjectByteWriterWithPosition::Write(const IOBas

Local<Value> args[1];
args[0] = anArray;

Local<Value> result = func->Call(GET_CURRENT_CONTEXT, OBJECT_FROM_PERSISTENT(mObject), 1, args).ToLocalChecked();
MaybeLocal<Value> maybe;
TryCatch try_catch(Isolate::GetCurrent());

maybe = func->Call(GET_CURRENT_CONTEXT, OBJECT_FROM_PERSISTENT(mObject), 1, args);
Local <Value> result;

if (!maybe.ToLocal(&result)) {
try_catch.ReThrow();
return 0;
}
if(result.IsEmpty())
{
THROW_EXCEPTION("wrong return value. it's empty. return the number of written characters");
return 0;
THROW_EXCEPTION("wrong return value. it's empty. return the number of written characters");
return 0;
}
else if(result->IsNumber())
{
return TO_UINT32(result)->Value();
}
else
{
THROW_EXCEPTION("wrong return value. write should return the number of written characters");
return 0;
THROW_EXCEPTION("wrong return value. write should return the number of written characters");
return 0;
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/deps/PDFWriter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ CIDFontWriter.h
CMYKRGBColor.h
ContainerIterator.h
DecryptionHelper.h
Deletable.h
DescendentFontWriter.h
DictionaryContext.h
DictOperand.h
Expand Down Expand Up @@ -234,6 +235,7 @@ IByteReaderWithPosition.h
IByteWriter.h
IByteWriterWithPosition.h
IContentContextListener.h
IDeletable.h
IDescendentFontWriter.h
IDocumentContextExtender.h
IFontDescriptorHelper.h
Expand Down Expand Up @@ -640,6 +642,8 @@ UppercaseSequance.h
)

source_group("PDF Embedding\\Parsed Objects" FILES
Deletable.h
IDeletable.h
PDFArray.cpp
PDFArray.h
PDFBoolean.cpp
Expand Down
11 changes: 6 additions & 5 deletions src/deps/PDFWriter/DecryptionHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ limitations under the License.
#include "InputRC4XcodeStream.h"
#include "InputAESDecodeStream.h"
#include "Trace.h"
#include "Deletable.h"
#include <memory>

using namespace std;
Expand Down Expand Up @@ -333,9 +334,9 @@ IByteReader* DecryptionHelper::CreateDefaultDecryptionFilterForStream(PDFStreamI
if (!IsEncrypted() || !CanDecryptDocument() || HasCryptFilterDefinition(mParser, inStream) || !mXcryptStreams)
return NULL;

void* savedEcnryptionKey = inStream->GetMetadata(scEcnryptionKeyMetadataKey);
IDeletable* savedEcnryptionKey = inStream->GetMetadata(scEcnryptionKeyMetadataKey);
if (savedEcnryptionKey) {
return CreateDecryptionReader(inToWrapStream, *((ByteList*)savedEcnryptionKey), mXcryptStreams->IsUsingAES());
return CreateDecryptionReader(inToWrapStream, *(((Deletable<ByteList>*)savedEcnryptionKey)->GetPtr()), mXcryptStreams->IsUsingAES());
}
else
return NULL;
Expand All @@ -346,15 +347,15 @@ IByteReader* DecryptionHelper::CreateDecryptionFilterForStream(PDFStreamInput*
if (!IsEncrypted() || !CanDecryptDocument())
return inToWrapStream;

void* savedEcnryptionKey = inStream->GetMetadata(scEcnryptionKeyMetadataKey);
IDeletable* savedEcnryptionKey = inStream->GetMetadata(scEcnryptionKeyMetadataKey);
if (!savedEcnryptionKey) {
// sign for no encryption here
return inToWrapStream;
}
XCryptionCommon* xcryption = GetFilterForName(mXcrypts, inCryptName);

if (xcryption && savedEcnryptionKey) {
return CreateDecryptionReader(inToWrapStream, *((ByteList*)savedEcnryptionKey), xcryption->IsUsingAES());
return CreateDecryptionReader(inToWrapStream, *(((Deletable<ByteList>*)savedEcnryptionKey)->GetPtr()), xcryption->IsUsingAES());
}
else
return inToWrapStream;
Expand Down Expand Up @@ -454,7 +455,7 @@ void DecryptionHelper::OnObjectEnd(PDFObject* inObject) {
XCryptionCommon* streamCryptFilter = GetCryptForStream((PDFStreamInput*)inObject);
if (streamCryptFilter) {
ByteList* savedKey = new ByteList(streamCryptFilter->GetCurrentObjectKey());
inObject->SetMetadata(scEcnryptionKeyMetadataKey, savedKey);
inObject->SetMetadata(scEcnryptionKeyMetadataKey,new Deletable<ByteList>(savedKey));
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/deps/PDFWriter/PDFDocumentHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2032,6 +2032,11 @@ EStatusCode PDFDocumentHandler::WriteStreamObject(PDFStreamInput* inStream, IObj
if(!readingDecrypted) {
streamReader = mParser->StartReadingFromStreamForPlainCopying(inStream);
}

if (streamReader == NULL) {
TRACE_LOG("PDFDocumentHandler::WriteStreamObject, unable to start reading stream object");
status = PDFHummus::eFailure;
}

while (it.MoveNext() && PDFHummus::eSuccess == status)
{
Expand Down
24 changes: 13 additions & 11 deletions src/deps/PDFWriter/PDFObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/
#include "PDFObject.h"
#include "IDeletable.h"

const char* PDFObject::scPDFObjectTypeLabel(int index)
{
Expand Down Expand Up @@ -53,9 +54,9 @@ PDFObject::PDFObject(int inType)

PDFObject::~PDFObject(void)
{
StringToVoidP::iterator it = mMetadata.begin();
StringToIDeletable::iterator it = mMetadata.begin();
for (; it != mMetadata.end(); ++it) {
delete it->second;
it->second->DeleteMe();
}
mMetadata.clear();
}
Expand All @@ -65,35 +66,36 @@ PDFObject::EPDFObjectType PDFObject::GetType()
return mType;
}

void PDFObject::SetMetadata(const std::string& inKey, void* inValue) {
void PDFObject::SetMetadata(const std::string& inKey, IDeletable* inValue) {
// delete old metadata
DeleteMetadata(inKey);

mMetadata.insert(StringToVoidP::value_type(inKey, inValue));
mMetadata.insert(StringToIDeletable::value_type(inKey, inValue));
}

void* PDFObject::GetMetadata(const std::string& inKey) {
StringToVoidP::iterator it = mMetadata.find(inKey);
IDeletable* PDFObject::GetMetadata(const std::string& inKey) {
StringToIDeletable::iterator it = mMetadata.find(inKey);

if (it == mMetadata.end())
return NULL;
else
return it->second;
}

void* PDFObject::DetachMetadata(const std::string& inKey) {
StringToVoidP::iterator it = mMetadata.find(inKey);
IDeletable* PDFObject::DetachMetadata(const std::string& inKey) {
StringToIDeletable::iterator it = mMetadata.find(inKey);

if (it == mMetadata.end())
return NULL;
else {
void* result = it->second;
IDeletable* result = it->second;
mMetadata.erase(it);
return result;
}
}

void PDFObject::DeleteMetadata(const std::string& inKey) {
void* result = DetachMetadata(inKey);
delete result;
IDeletable* result = DetachMetadata(inKey);
if(result)
result->DeleteMe();
}
12 changes: 7 additions & 5 deletions src/deps/PDFWriter/PDFObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
#include <string>
#include <map>

typedef std::map<std::string, void*> StringToVoidP;
class IDeletable;

typedef std::map<std::string, IDeletable*> StringToIDeletable;

class PDFObject : public RefCountObject
{
Expand Down Expand Up @@ -58,14 +60,14 @@ class PDFObject : public RefCountObject
/*
metadata will automatically be deleted when object is released
*/
void SetMetadata(const std::string& inKey,void* inValue); // will automatically delete old data in the same key
void* GetMetadata(const std::string& inKey);
void SetMetadata(const std::string& inKey,IDeletable* inValue); // will automatically delete old data in the same key
IDeletable* GetMetadata(const std::string& inKey);
// Detach will only remove the pointer from metadata map, Delete will also delete the inValue pointer
void* DetachMetadata(const std::string& inKey);
IDeletable* DetachMetadata(const std::string& inKey);
void DeleteMetadata(const std::string& inKey);


private:
EPDFObjectType mType;
StringToVoidP mMetadata;
StringToIDeletable mMetadata;
};
8 changes: 8 additions & 0 deletions src/deps/PDFWriter/PDFObjectParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,4 +706,12 @@ void PDFObjectParser::SetDecryptionHelper(DecryptionHelper* inDecryptionHelper)
void PDFObjectParser::SetParserExtender(IPDFParserExtender* inParserExtender)
{
mParserExtender = inParserExtender;
}

IByteReader* PDFObjectParser::StartExternalRead() {
return mStream;
}

void PDFObjectParser::EndExternalRead() {
ResetReadState();
}
6 changes: 6 additions & 0 deletions src/deps/PDFWriter/PDFObjectParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class PDFObjectParser
// Assign the stream to read from (does not take ownership of the stream, unless told so)
void SetReadStream(IByteReader* inSourceStream,IReadPositionProvider* inCurrentPositionProvider,bool inOwnsStream=false);

// the important bit - get next object in content stream
PDFObject* ParseNewObject();

// calls this when changing underlying stream position
Expand All @@ -64,6 +65,11 @@ class PDFObjectParser
// helper method for others who need to parse encoded pdf data
std::string DecodeHexString(const std::string inStringToDecode);

// External reading. use to temporarily get access to the internal stream, instead of reading objects with ParseNewObject.
// when done mark with FinishExternalReading to commence reading
IByteReader* StartExternalRead();
void EndExternalRead();

private:
PDFParserTokenizer mTokenizer;
StringList mTokenBuffer;
Expand Down
6 changes: 6 additions & 0 deletions src/deps/PDFWriter/PDFParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,12 @@ EStatusCode PDFParser::ParseLastXrefPosition()
mObjectParser.ResetReadState();
RefCountPtr<PDFObject> anObject(mObjectParser.ParseNewObject());

if (!anObject) {
status = PDFHummus::eFailure;
TRACE_LOG("PDFParser::ParseXrefPosition: Unable to find any object");
break;
}

if(anObject->GetType() == PDFObject::ePDFObjectInteger)
{
mLastXrefPosition = (LongFilePositionType)((PDFInteger*)anObject.GetPtr())->GetValue();
Expand Down
13 changes: 12 additions & 1 deletion tests/AppendPagesTest.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
var hummus = require('../hummus');
const expect = require('chai').expect;

describe('AppendPagesTest', function() {
it('should complete without error', function() {
var pdfWriter = require('../hummus').createWriter(__dirname + '/output/AppendPagesTest.pdf');
var pdfWriter = hummus.createWriter(__dirname + '/output/AppendPagesTest.pdf');

pdfWriter.appendPDFPagesFromPDF(__dirname + '/TestMaterials/Original.pdf');
pdfWriter.appendPDFPagesFromPDF(__dirname + '/TestMaterials/XObjectContent.PDF');
pdfWriter.appendPDFPagesFromPDF(__dirname + '/TestMaterials/BasicTIFFImagesTest.PDF');

pdfWriter.end();
});

it('should throw an error instead of a crash', () => {
var writerBuffer = new hummus.PDFWStreamForBuffer([]);
var pdfWriter = hummus.createWriter(writerBuffer)
expect(() =>
pdfWriter.appendPDFPagesFromPDF(__dirname + '/TestMaterials/appendbreaks.pdf')
).to.throw('unable to append')
})
});
8 changes: 8 additions & 0 deletions tests/BasicModificationWithStreams.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var hummus = require('../hummus');
const chai = require('chai');

describe('BasicModificationWithStreams', function() {
it('should complete without error', function() {
Expand All @@ -19,4 +20,11 @@ describe('BasicModificationWithStreams', function() {
outStream.close();
inStream.close();
});

it('null for stream should throw an error and not crash', function () {
var res = new hummus.PDFStreamForResponse(null)
chai.expect(
hummus.createWriter.bind(undefined, res)
).to.throw(/Cannot read propert.*(write)?.* of null/)
})
});

0 comments on commit a9bf252

Please sign in to comment.