C# Web アプリケーションがあり、pdf ドキュメントに相互参照ストリームが含まれているかどうかを確認したいと考えています。相互参照ストリームが含まれている場合は、それを参照テーブルに変換します。
3 に答える
検出はかなり簡単です。ファイルの末尾から「%%EOF」を検索します。適切な PDF ファイルは実際には '%%EOF' 行で終わります。そのため、適切な PDF ファイルにはそのマーカーの後にゴミバイトが含まれる場合があります。そのマーカー行の前の行には、最後の相互参照の位置が含まれています ( ISO-32000-1:2008セクション 7.5.5 の Adobe コピーを参照)。ここに記載されている位置に移動します。
その位置に xref キーワードがある場合、PDF には相互参照テーブルがあります。代わりに PDF ストリーム オブジェクトが見つかった場合 (同書セクション 7.5.8)、PDF には相互参照ストリームがあります。どちらも見つからない場合は、ファイルに怪しいものがあります。
ただし、相互参照ストリームでのみ使用できるオブジェクト ストリームも PDF で使用されている場合は特に、変換は困難です。iText(Sharp) などのライブラリを使用して PDF を読み取り、圧縮を減らして再度エクスポートすることをお勧めします。
さらに、PDF が署名されている場合、署名を壊さずに変換することはできません。
ハックのようなものですが、次のコードを使用して、PDF に相互参照ストリームが含まれているかどうかを検出できます。
コードはDocotic.Pdf ライブラリを使用します。
public static bool ContainsCrossReferenceStreams(string fileName)
{
using (PdfDocument document = new PdfDocument(fileName))
{
return document.SaveOptions.UseObjectStreams;
}
}
ライブラリが PDF を開くと、ソース ドキュメントが相互参照ストリームを使用する場合に設定SaveOptions.UseObjectStreams
されます。true
それ以外の場合、プロパティは を返しますfalse
。
免責事項: 私はライブラリのベンダーで働いています。
相互参照ストリームを解析可能なものに変換する際に注意すべきことの 1 つは、相互参照ストリームが新しいタイプの参照エントリを許可することです。"uncompressed"と"free"に加えて、新しい参照タイプとして"compressed"が追加されました。
このエントリを通常のクロスリファレンス テーブルに直接 1:1 で変換することはできません。相互参照ストリーム内の「圧縮された」参照エントリは、いわゆる「オブジェクト ストリーム」を指します。後者には、複数のインデックス付きオブジェクトが含まれています。外部参照ストリームの「圧縮された」エントリは、オブジェクト ストリームとインデックスに名前を付けます。次に、オブジェクト ストリーム内の最初の行を使用して、インデックスをオブジェクト ストリーム内のバイト オフセットに解決します。
そのトピックがまだ興味がある場合は、「3.4.7 相互参照ストリーム」の章をご覧になることをお勧めします。特に、「PDF 1.5 をサポートしないアプリケーションとの互換性」という段落が役に立ちます。どういうわけかあなたが望むことをする、いわゆる「ハイブリッド参照」を扱います。
これで、外部参照ストリームを外部参照テーブルに変換する方法がある程度わかったので、外部参照ストリームの検出に進みましょう。
- /Type/XRefを使用してストリームを検索できます(2 つのキーワードの間に可変スペースを使用)。
- また、/Type/ObjStmのストリームがある場合は、xref ストリームのみがオブジェクト ストリームを指すことができるため、xref ストリームが存在する必要があると推測できます ;) (説明については上記を参照してください)。
- 最後になりましたが、解析するドキュメントのPDF バージョンが1.5 未満の場合、xref ストリームが含まれていないことをある程度確信できます。これは、ドキュメントを作成した PDF オーサリング ツールに大きく依存します。参照に固執するものもあれば、そうでないものもあります。
これが役立つことを願っています。