ParseObject: Fix stream parsing, detecting "endstream" when it is unavailable on the dictionary (forward references or missing)
This commit is contained in:
@@ -56,6 +56,33 @@ namespace VAR.PdfTools
|
|||||||
return memStream.ToArray();
|
return memStream.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TestMarker(long position, char[] marker)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < marker.Length; i++)
|
||||||
|
{
|
||||||
|
if ((position + i) >= _stream.Length) { return false; }
|
||||||
|
if(_stream[position+i] != marker[i]) { return false; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long MeasureToMarkers(char[][] markers)
|
||||||
|
{
|
||||||
|
long position = _streamPosition;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
foreach(char[] marker in markers)
|
||||||
|
{
|
||||||
|
if (TestMarker(position, marker))
|
||||||
|
{
|
||||||
|
return (position - _streamPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
position++;
|
||||||
|
} while (position < _stream.Length);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private byte PeekChar()
|
private byte PeekChar()
|
||||||
{
|
{
|
||||||
if (_streamPosition >= _stream.Length)
|
if (_streamPosition >= _stream.Length)
|
||||||
@@ -107,9 +134,11 @@ namespace VAR.PdfTools
|
|||||||
|
|
||||||
private bool IsEndOfLine(byte character)
|
private bool IsEndOfLine(byte character)
|
||||||
{
|
{
|
||||||
|
byte lineFeed = 0x0A;
|
||||||
|
byte carriageReturn = 0x0D;
|
||||||
if (
|
if (
|
||||||
character == 0x0A || // Line Feed (LF)
|
character == lineFeed ||
|
||||||
character == 0x0D || // Carriage Return (CR)
|
character == carriageReturn ||
|
||||||
false)
|
false)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@@ -174,7 +203,7 @@ namespace VAR.PdfTools
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (PeekChar() != lineFeed)
|
if (PeekChar() == lineFeed)
|
||||||
{
|
{
|
||||||
NextChar();
|
NextChar();
|
||||||
return;
|
return;
|
||||||
@@ -687,12 +716,23 @@ namespace VAR.PdfTools
|
|||||||
{
|
{
|
||||||
throw new Exception(string.Format("Stream after a not dictionary element at: {0}", _streamPosition));
|
throw new Exception(string.Format("Stream after a not dictionary element at: {0}", _streamPosition));
|
||||||
}
|
}
|
||||||
if (streamDict.Values.ContainsKey("Length") == false)
|
|
||||||
{
|
|
||||||
throw new Exception(string.Format("Dictionary of stream does not specify Lenght at: {0}", _streamPosition));
|
|
||||||
}
|
|
||||||
long length = ((PdfInteger)streamDict.Values["Length"]).Value;
|
|
||||||
SkipEndOfLine();
|
SkipEndOfLine();
|
||||||
|
long length;
|
||||||
|
if (streamDict.Values.ContainsKey("Length") && streamDict.Values["Length"] is PdfInteger)
|
||||||
|
{
|
||||||
|
length = ((PdfInteger)streamDict.Values["Length"]).Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte lineFeed = 0x0A;
|
||||||
|
byte carriageReturn = 0x0D;
|
||||||
|
length = MeasureToMarkers(new char[][] {
|
||||||
|
new char[] {(char)carriageReturn, (char)lineFeed, 'e', 'n', 'd', 's', 't', 'r', 'e', 'a', 'm'},
|
||||||
|
new char[] {(char)lineFeed, 'e', 'n', 'd', 's', 't', 'r', 'e', 'a', 'm'},
|
||||||
|
new char[] {'e', 'n', 'd', 's', 't', 'r', 'e', 'a', 'm', (char)lineFeed},
|
||||||
|
new char[] {'e', 'n', 'd', 's', 't', 'r', 'e', 'a', 'm', (char)carriageReturn, (char)lineFeed},
|
||||||
|
});
|
||||||
|
}
|
||||||
byte[] streamBody = GetRawData(length);
|
byte[] streamBody = GetRawData(length);
|
||||||
SkipEndOfLine();
|
SkipEndOfLine();
|
||||||
endToken = ParseToken();
|
endToken = ParseToken();
|
||||||
|
|||||||
Reference in New Issue
Block a user