internal PdfName ReadName(IPdfStreamReader streamReader) { var nameStart = streamReader.Read(); if (nameStart != '/') { throw new InvalidDataException("Unexpected name start character, expected /"); } var token = streamReader.ReadNextToken(); var result = this.ParseName(((char)nameStart) + token); return(result); }
internal PdfArray ReadArray(IPdfStreamReader streamReader, IPdf pdf) { var arrayInit = streamReader.Read(); if (arrayInit != '[') { throw new InvalidDataException("Unexpected array initializer, expected ["); } var items = new List <PdfObject>(); streamReader.SeekToNextToken(); while (true) { var item = this.ReadObject(streamReader, pdf); if (item != null) { items.Add(item); } else { //ignore whitespace if (streamReader.PeekIsNextByteWhitespace()) { streamReader.Seek(1, SeekOrigin.Current); } else if (streamReader.Peek() == ']') { //we're at the end of the array, do nothing, it gets handled below. } else { throw new InvalidDataException("Unable to parse array, invalid object."); } } if (streamReader.Peek() == ']') { streamReader.Seek(1, SeekOrigin.Current); streamReader.SeekToNextToken(); break; } } return(items.ToArray()); }
internal PdfBinaryString ReadBinaryString(IPdfStreamReader streamReader, PdfOptions options) { var start = streamReader.Read(); if (start != '<') { throw new InvalidDataException("Invalid starting character, should be <"); } var data = new StringBuilder(); var buffer = new byte[512]; int endIndex; while (true) { //read in a buffer of data to make it fast. var read = streamReader.Peek(buffer, 0, buffer.Length); var bufferText = Encoding.ASCII.GetString(buffer, 0, read); if ((endIndex = bufferText.IndexOf(">")) >= 0) { if (endIndex != 0) { data.Append(bufferText.Substring(0, endIndex)); } streamReader.Seek(endIndex + 1, SeekOrigin.Current); break; } else { data.Append(bufferText); streamReader.Seek(read + 1, SeekOrigin.Current); } } streamReader.SeekToNextToken(); var result = data.ToString().GetBytesFromHexString(); return(result); }
internal PdfString ReadString(IPdfStreamReader streamReader) { var startPosition = streamReader.Position; var parenthesisCount = 0; var buffer = new byte[512]; var escaped = false; var currentCharacterCode = (string)null; var result = string.Empty; var totalStringBytes = 0; var foundEndOfString = false; var goingToNewLine = false; while (true) { var bytesRead = streamReader.Read(buffer, 0, buffer.Length); if (bytesRead <= 0) { throw new InvalidDataException("Unexpected end of stream"); } for (var index = 0; index < bytesRead; index++) { totalStringBytes++; var c = (char)buffer[index]; if (escaped) { escaped = false; if (goingToNewLine && (c != '\r' && c != '\n')) { escaped = false; goingToNewLine = false; result += c; continue; } //handled escape characters if (c == '\r' || c == '\n') { escaped = true; goingToNewLine = true; } else if (c == 'n') { result += '\n'; } else if (c == 'r') { result += '\r'; } else if (c == 't') { result += '\t'; } else if (c == 'b') { result += '\b'; } else if (c == 'f') { result += '\f'; } else if (c == '(' || c == ')' || c == '\\') { result += c.ToString(); } else if (c >= '0' && c <= '9') { if (currentCharacterCode == null) { currentCharacterCode = c.ToString(); escaped = true; } else if (currentCharacterCode.Length < 3) { currentCharacterCode += c.ToString(); escaped = true; } if (currentCharacterCode.Length == 3) { result += (char)Convert.ToByte(currentCharacterCode, 8); currentCharacterCode = null; escaped = false; } } else if (currentCharacterCode != null) { result += $"{(char)Convert.ToByte(currentCharacterCode, 8)}{c}"; currentCharacterCode = null; } else { throw new InvalidDataException("Invalid escaped character: " + c); } } else if (c == '(') { if (parenthesisCount > 0) { result += c; } parenthesisCount++; } else if (c == ')') { parenthesisCount--; if (parenthesisCount > 0) { result += c; } else { foundEndOfString = true; break; } } else if (c == '\\') { escaped = true; } else { result += c; } } if (foundEndOfString) { break; } } streamReader.Seek(startPosition + totalStringBytes, SeekOrigin.Begin); streamReader.SeekToNextToken(); return(result); }
internal PdfStream ReadStream(IPdfStreamReader streamReader, IPdf pdf, PdfDictionary streamDictionary) { PdfNumber length = null; var lengthEntry = streamDictionary["Length"]; if (lengthEntry == null) { throw new InvalidDataException("Unable to get required stream length. Entry not found."); } if (lengthEntry is PdfNumber) { length = lengthEntry as PdfNumber; } else if (lengthEntry is PdfReference reference) { //oh yay, we need to go dig through the pdf content for the correct value var referenceEntry = pdf.CrossReferenceTable.Find(reference.ObjectNumber, reference.Generation); lengthEntry = this.PeekReadObject(streamReader, pdf, referenceEntry); length = lengthEntry as PdfNumber; } if (length == null) { throw new InvalidDataException("Unable to get required stream length. Value not found."); } var buffer = new byte[length]; var firstDataBuffer = new byte[6]; streamReader.Read(firstDataBuffer, 0, 6); //the word stream streamReader.Peek(firstDataBuffer, 0, 2); // the CR+LF or LF int seekLength; if (firstDataBuffer[0] == 0xD && firstDataBuffer[1] == 0xA) { seekLength = 2; } else if (firstDataBuffer[0] == 0xA) { seekLength = 1; } else { throw new InvalidDataException("Unexpected end of line characters, expected CR+LF or just LF"); } streamReader.Seek(seekLength, SeekOrigin.Current); var bytesRead = streamReader.Read(buffer, 0, buffer.Length); //read the data if (bytesRead != buffer.Length) { throw new InvalidDataException("Unexpected end of file while reading the data stream"); } streamReader.SeekToNextToken(true); //end of line at the end of the stream is ok. var endOfStreamToken = streamReader.ReadNextToken(); if (endOfStreamToken != "endstream") { throw new InvalidDataException("Unexpected end of stream token, expected endstream"); } var result = new PdfStream(streamDictionary, buffer); return(result); }