2013-10-02 1 views
-1

У меня есть код на C#, который извлекает все вложения из PDF-файлов. Он отлично работает, даже если он прикреплен к уровню документа или в виде аннотации файла.Как извлечь приложение из PDF с цифровой подписью?

Однако, если я в цифровом виде подпишу (и временную метку) этих файлов PDF, тип вложения изменяется от аннотации (или прикрепления файла) до «виджета» или чего-то еще. Я не эксперт по pdf, и я не смог найти какой-либо метод для извлечения вложений, если PDF подписан.

Любая помощь оценена!

[EDIT]

образца без подписи: samplepdf_notsigned.pdf

образца с подписью (подписанного с SetaPDF-синьора API): samplepdf_signed.pdf

Вложенные блоки являются следующие:

/* 
* annotations 
*/ 
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader("samplepdf_annotations.pdf"); 
for (int i = 1; i <= reader.NumberOfPages; i++) 
{ 
    iTextSharp.text.pdf.PdfArray array = reader.GetPageN(i).GetAsArray(iTextSharp.text.pdf.PdfName.ANNOTS); 
    if (array == null) continue; 
    for (int j = 0; j < array.Size; j++) 
    { 
     iTextSharp.text.pdf.PdfDictionary annot = array.GetAsDict(j); 
     if (iTextSharp.text.pdf.PdfName.FILEATTACHMENT.Equals(annot.GetAsName(iTextSharp.text.pdf.PdfName.SUBTYPE))) 
     { 
      iTextSharp.text.pdf.PdfDictionary fs = annot.GetAsDict(iTextSharp.text.pdf.PdfName.FS); 
      iTextSharp.text.pdf.PdfDictionary refs = fs.GetAsDict(iTextSharp.text.pdf.PdfName.EF); 
      foreach (iTextSharp.text.pdf.PdfName name in refs.Keys) 
      { 
       // I CAN GET THE ATTACHMENT HERE 
       string filename = fs.GetAsString(name).ToString(); 
       byte[] binary = iTextSharp.text.pdf.PdfReader.GetStreamBytes((iTextSharp.text.pdf.PRStream)refs.GetAsStream(name)); 
      } 
     } 
     else 
     { 
      iTextSharp.text.pdf.PdfDictionary fs = annot.GetAsDict(iTextSharp.text.pdf.PdfName.FS); 
      iTextSharp.text.pdf.PdfDictionary refs = fs.GetAsDict(iTextSharp.text.pdf.PdfName.EF); 
      foreach (iTextSharp.text.pdf.PdfName name in refs.Keys) 
      { 
       // I CAN GET THE ATTACHMENT HERE 
       string filename = fs.GetAsString(name).ToString(); 
       byte[] binary = iTextSharp.text.pdf.PdfReader.GetStreamBytes((iTextSharp.text.pdf.PRStream)refs.GetAsStream(name)); 
      } 
     } 
    } 
} 

/* 
* embedded level 
*/ 
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader("samplepdf_embedded.pdf"); 
iTextSharp.text.pdf.PdfDictionary root = reader.Catalog; 
iTextSharp.text.pdf.PdfDictionary documentnames = root.GetAsDict(iTextSharp.text.pdf.PdfName.NAMES); 
iTextSharp.text.pdf.PdfDictionary embeddedfiles = documentnames.GetAsDict(iTextSharp.text.pdf.PdfName.EMBEDDEDFILES); 
iTextSharp.text.pdf.PdfArray filespecs = embeddedfiles.GetAsArray(iTextSharp.text.pdf.PdfName.NAMES); 
for (int i = 0; i < filespecs.Size;) { 
    filespecs.GetAsString(i++); 
    iTextSharp.text.pdf.PdfDictionary filespec = filespecs.GetAsDict(i++); 
    iTextSharp.text.pdf.PdfDictionary refs = filespec.GetAsDict(iTextSharp.text.pdf.PdfName.EF); 
    foreach (iTextSharp.text.pdf.PdfName key in refs.Keys) 
    { 
     iTextSharp.text.pdf.PRStream stream = (iTextSharp.text.pdf.PRStream)iTextSharp.text.pdf.PdfReader.GetPdfObject(refs.GetAsIndirectObject(key)); 
     // I CAN GET THE ATTACHMENT HERE 
     string filename = filespec.GetAsString(key).ToString(); 
     byte[] binary = iTextSharp.text.pdf.PdfReader.GetStreamBytes(stream); 
    } 
} 
+0

Вы должны предоставить дополнительную информацию. Например. как ваш текущий код извлекает вложения? Как вы подписываете и помечены в формате PDF? Кроме того, могут помочь образцы документов (как без знака, так и подписи). – mkl

+0

Сообщение отредактировано, я добавил свой код и некоторые примеры файлов PDF. Благодаря! – aboy

+0

А что именно происходит? Я предполагаю нулевой доступ? – mkl

ответ

0

Я предполагаю, что проблема находится в вашем верхнем блоке кода, который пытается найти аннотации прикрепления файлов. В своем внутреннем цикле (который инспектирует каждую аннотацию) у вас есть конструкция:

if (iTextSharp.text.pdf.PdfName.FILEATTACHMENT.Equals(annot.GetAsName(iTextSharp.text.pdf.PdfName.SUBTYPE))) 
{ 
    [...block 1...] 
} 
else 
{ 
    [...block 2...] 
} 

Здесь блокировать 1 и 2 одинаковы, т.е. вы выполняете код там в любом случае, как для аннотаций, которые являются файлом вложения и аннотации, которые не являются.

Пока только аннотации в PDF-файлах являются файловыми вложениями, что не имеет значения, но как только есть один другая аннотация, код в этом блоке 2

iTextSharp.text.pdf.PdfDictionary fs = annot.GetAsDict(iTextSharp.text.pdf.PdfName.FS); 
iTextSharp.text.pdf.PdfDictionary refs = fs.GetAsDict(iTextSharp.text.pdf.PdfName.EF); 
foreach (iTextSharp.text.pdf.PdfName name in refs.Keys) 
{ 
    // I CAN GET THE ATTACHMENT HERE 
    string filename = fs.GetAsString(name).ToString(); 
    byte[] binary = iTextSharp.text.pdf.PdfReader.GetStreamBytes((iTextSharp.text.pdf.PRStream)refs.GetAsStream(name)); 
} 

, скорее всего, взрывает в ваше лицо, потому что большинство других типов аннотаций не имеют записи /EF, поэтому refs - null и refs.Keys вызывает исключение.

К сожалению, для вас интегрированные подписи PDF являются полями формы, которые (даже если они невидимы) могут быть прикреплены к какой-либо странице в виде аннотаций. Таким образом, подписание PDF приводит к ловушке в блоке 2.

Возникает вопрос, почему вы пытаетесь извлечь вложения в блок 2 в любом случае. Согласно спецификации PDF, аннотации прикрепления файла должны содержать информацию о типе, которую ищет if. Таким образом, ни один из совместимых с спецификацией PDF файлов не превратит ваш код в блок 2 для аннотаций присоединения файлов. Таким образом, вы можете просто удалить этот блок 2.

+0

Вы правы, блок 2 неверен (делать то же, что и в блоке 1). Любая идея, как получить вложение, когда PDF подписан? Могу ли я связаться с ними напрямую или сначала удалить подпись (поля чистой формы)? Если да, то как я могу это сделать с iTextSharp? – aboy

+0

Почему вы пытаетесь извлечь вложения файлов из аннотаций, которые являются ** не ** аннотациями прикрепления файлов? Блок 2 ничего не должен делать. И если вы считаете, что могут быть аннотации, которые неправильно помечены, вы должны проверить каждый объект, который вы пытаетесь получить для «null». – mkl