From 9b615852df5f56eeb67c4dd021a56e72d31a2498 Mon Sep 17 00:00:00 2001
From: tknall <tknall@7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c>
Date: Mon, 14 Dec 2009 13:47:48 +0000
Subject: Error code created for protected pdf documents. SettingsReader: Debug
 message for getInternalResource added (TRACE) multipart/formdata: align
 multipart charset with data charset added FIXME notes for
 FileHelper.readFromFile Signature/Verification-Demo updated

git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@507 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c
---
 .../egiz/pdfas/api/timestamp/DummyTimeStamper.java | 10 +++++-----
 .../gv/egiz/pdfas/api/timestamp/TimeStamper.java   |  2 +-
 .../at/gv/egiz/pdfas/exceptions/ErrorCode.java     |  1 +
 .../exceptions/pdf/TextExtractionException.java    | 23 ----------------------
 .../egiz/pdfas/impl/input/TextDataSourceImpl.java  |  8 +++++---
 .../wag/egov/egiz/cfg/SettingsReader.java          | 10 +++++++++-
 .../wag/egov/egiz/pdf/TextualSignature.java        | 14 +++++++------
 .../wag/egov/egiz/sig/connectors/BKUConnector.java |  2 ++
 .../wag/egov/egiz/sig/connectors/MOAConnector.java |  4 ++++
 .../egiz/sig/connectors/bku/BKUPostConnection.java |  6 ++++--
 .../egiz/sig/connectors/moa/MOASoapConnection.java |  6 ++++--
 src/main/java/demo/SignatureCreationDemo.java      | 15 ++++++++++++--
 src/main/java/demo/SignatureVerificationDemo.java  | 15 +++++++++++---
 src/main/resources/config/help_text.properties     |  1 +
 14 files changed, 69 insertions(+), 48 deletions(-)
 delete mode 100644 src/main/java/at/gv/egiz/pdfas/exceptions/pdf/TextExtractionException.java

diff --git a/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java b/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java
index c2532e8..c9c7ae7 100644
--- a/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java
+++ b/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java
@@ -3,6 +3,7 @@ package at.gv.egiz.pdfas.api.timestamp;
 import java.util.Date;
 
 import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.time.DateFormatUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -18,12 +19,11 @@ public class DummyTimeStamper implements TimeStamper {
    private String lastTimeStamp;
 
    public String applyTimeStamp(String b64SignatureValue) {
-      log.debug("execute dummy timestamp on value: " + b64SignatureValue);
-      String ts = ("my dummy timestamp " + new Date());
-      log.debug("timestamp: " + ts);
-
+      log.debug("Applying dummy timestamp on signature value: " + b64SignatureValue);
+      String ts = DateFormatUtils.format(new Date(), "yyyy-MM-dd'T'hh:mm:ss.SSSZ");
+      log.debug("Timestamp: " + ts);
       ts = new String(Base64.encodeBase64(ts.getBytes()));
-      log.debug("timestamp b64: " + ts);
+      log.debug("Timestamp value (base64): " + ts);
       this.lastTimeStamp  = ts;
       return ts;
    }
diff --git a/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java b/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java
index 7100310..c39d78e 100644
--- a/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java
+++ b/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java
@@ -11,7 +11,7 @@ public interface TimeStamper {
    /**
     * Implement timestamp in this method. 
     * @param b64SignatureValue signature value, base64 encoded
-    * @return timestamp to be embedded in egiz dict. base64 encoded
+    * @return timestamp to be embedded in egiz dictionary base64 encoded (following RFC3161).
     */
    public String applyTimeStamp(String b64SignatureValue);
 
diff --git a/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java b/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java
index 857fc09..04cf779 100644
--- a/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java
+++ b/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java
@@ -28,6 +28,7 @@ public final class ErrorCode
   public static final int DOCUMENT_NOT_SIGNED = 206;
   public static final int SIGNATURE_TYPES_EXCEPTION = 223;
   public static final int FONT_NOT_FOUND = 230;
+  public static final int DOCUMENT_IS_PROTECTED = 231;
   
   public static final int SIGNATURE_COULDNT_BE_CREATED = 300;
   public static final int SIGNED_TEXT_EMPTY = 301;
diff --git a/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/TextExtractionException.java b/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/TextExtractionException.java
deleted file mode 100644
index 6586dd0..0000000
--- a/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/TextExtractionException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package at.gv.egiz.pdfas.exceptions.pdf;
-
-import at.gv.egiz.pdfas.exceptions.ErrorCode;
-import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
-
-public class TextExtractionException extends PresentableException
-{
-  /**
-   * SVUID.
-   */
-  private static final long serialVersionUID = 2798763345488999563L;
-
-  public TextExtractionException(Throwable cause)
-  {
-    super(ErrorCode.TEXT_EXTRACTION_EXCEPTION, cause);
-  }
-  
-  public TextExtractionException(String message)
-  {
-    super(ErrorCode.TEXT_EXTRACTION_EXCEPTION, message);
-  }
-
-}
diff --git a/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java b/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java
index c983a8a..077ed97 100644
--- a/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java
+++ b/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java
@@ -26,6 +26,8 @@ public class TextDataSourceImpl implements TextDataSource
    * The text.
    */
   protected String text = null;
+  
+  private final static String CHARSET = "UTF-8";
 
   /**
    * Constructor that sets the text.
@@ -53,7 +55,7 @@ public class TextDataSourceImpl implements TextDataSource
   {
     try
     {
-      byte[] data = getText().getBytes("UTF-8");
+      byte[] data = getText().getBytes(CHARSET);
       // PERF: if memory is an issue (e.g. in web), use a FileBased TextDataSource instead.
       return new ByteArrayInputStream(data);
     }
@@ -70,7 +72,7 @@ public class TextDataSourceImpl implements TextDataSource
   {
     try
     {
-      byte[] data = getText().getBytes("UTF-8");
+      byte[] data = getText().getBytes(CHARSET);
       return data.length;
     }
     catch (UnsupportedEncodingException e)
@@ -86,7 +88,7 @@ public class TextDataSourceImpl implements TextDataSource
   {
     try
     {
-      byte[] data = getText().getBytes("UTF-8");
+      byte[] data = getText().getBytes(CHARSET);
       return data;
     }
     catch (UnsupportedEncodingException e)
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java b/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
index 4ae64a2..2da0d61 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
@@ -631,7 +631,15 @@ public class SettingsReader implements Serializable
    * @return
    */
   public InputStream getInternalResource(String relativePath) {
-     return this.getClass().getResourceAsStream(INTERNAL_RESOURCE_PATH + relativePath);
+     String streamURI = INTERNAL_RESOURCE_PATH + relativePath;
+     logger_.trace("Trying to get stream from \"" + streamURI + "\".");
+     InputStream stream = this.getClass().getResourceAsStream(streamURI);
+     if (stream == null) {
+        logger_.trace("Could not get stream.");
+     } else {
+        logger_.trace("Got stream.");
+     }
+     return stream;
   }
   
   /**
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java
index d5b3c5d..c2a253b 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java
@@ -27,11 +27,12 @@ import org.pdfbox.pdfparser.PDFParser;
 import org.pdfbox.pdmodel.PDDocument;
 import org.pdfbox.util.PDFTextStripper;
 
-import at.gv.egiz.pdfas.exceptions.pdf.TextExtractionException;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
 import at.gv.egiz.pdfas.framework.input.PdfDataSource;
 import at.gv.egiz.pdfas.performance.PerformanceCounters;
 import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
 import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
 
 import com.lowagie.text.Document;
 import com.lowagie.text.DocumentException;
@@ -59,10 +60,11 @@ public class TextualSignature
    * @param pdf_stream
    *          The pdf_input stream.
    * @return Returns the extracted document text.
+ * @throws PDFDocumentException 
    * @throws TextExtractionException
    *           Forwarded exception.
    */
-  public static String extractTextTextual(PdfDataSource pdfDataSource) throws TextExtractionException
+  public static String extractTextTextual(PdfDataSource pdfDataSource) throws PDFDocumentException 
   {
     PerformanceCounters.textExtractions.increment();
     
@@ -85,7 +87,7 @@ public class TextualSignature
         PdfReader reader = new PdfReader(pdf_data);
         if (!reader.isOpenedWithFullPermissions()) {
            // cannot perform modification and extraction
-           throw new TextExtractionException("Document is protected");
+           throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected.");
            
         }
         //pdf_stream.close();
@@ -178,15 +180,15 @@ public class TextualSignature
     }
     catch (IllegalArgumentException e)
     {
-      throw new TextExtractionException(e);
+       throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
     }
     catch (IOException e)
     {
-      throw new TextExtractionException(e);
+      throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
     }
     catch (DocumentException e)
     {
-      throw new TextExtractionException(e);
+       throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
     }
   }
   
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
index c5ab9f5..c02b2c9 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
@@ -626,6 +626,7 @@ public class BKUConnector implements LocalConnector
     String keybox_identifier = getSignKeyboxIdentifier(signType);
     String sign_request_filename = getSignRequestTemplateFileName(signType);
 
+    // FIXME[tknall]: might fail since template has been moved to library
     String sign_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
     if (logger_.isDebugEnabled())
     {
@@ -650,6 +651,7 @@ public class BKUConnector implements LocalConnector
       SignatureObject sigObject) throws SignatureException
   {
     String verify_request = getVerifyRequestTemplateFileName(sigObject.getSignationType());
+    // FIXME[tknall]: might fail since template has been moved to library
     String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request));
 
     if (logger_.isDebugEnabled())
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java
index 7406ccd..30bffb7 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java
@@ -181,6 +181,7 @@ public class MOAConnector implements Connector
 
     String sign_request_filename = getSignRequestTemplateFileName(sigType);
     String key_ident = getSignKeyIdentifier(sigType);
+    // FIXME[tknall]: might fail since template has been moved to library
     String sign_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
     if (sign_req_str == null)
     {
@@ -413,7 +414,9 @@ public class MOAConnector implements Connector
       }
       String verify_template = getVerifyTemplateFileName(sigObject.getSignationType());
       String sig_prop_template = getSigPropFileName(sigObject.getSignationType());
+      // FIXME[tknall]: might fail since template has been moved to library
       String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_template));
+      // FIXME[tknall]: might fail since template has been moved to library
       String sig_prop_str = FileHelper.readFromFile(SettingsReader.relocateFile(sig_prop_template));
 
       if (logger_.isDebugEnabled())
@@ -522,6 +525,7 @@ public class MOAConnector implements Connector
     // +
     // ".request");
     String trust_profile = getVerifyTrustProfileID(sigObject.getSignationType());
+    // FIXME[tknall]: might fail since template has been moved to library
     String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request));
 
     String verify_template_str = null;
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java
index d2cffe8..6ea8ced 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java
@@ -100,8 +100,10 @@ public final class BKUPostConnection
     //ByteArrayPartSource baps = new ByteArrayPartSource(filename, data.getData());
     FilePart filepart = new FilePart("fileupload", ps); //$NON-NLS-1$
     filepart.setContentType(data.getMimeType());
-    // this is optional
-    // filepart.setCharSet(data.getCharacterEncoding());
+
+    // not really needed since external referenced data has to be taken "as-is" (binary stream) for
+    // digest calculation, so neither content type nor charset is relevant
+    filepart.setCharSet(data.getCharacterEncoding());
 
     Part[] parts = { xmlpart, filepart };
 
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java
index d0448cb..38998c4 100644
--- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java
+++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java
@@ -198,8 +198,10 @@ public final class MOASoapConnection
 	    FilePartMR filepart = new FilePartMR("fileupload", ps); //$NON-NLS-1$
 	    filepart.setContentType(data.getMimeType());
 	    filepart.setContentID("<fileupload>");
-	    // this is optional
-	    // filepart.setCharSet(data.getCharacterEncoding());
+
+	    // not really needed since external referenced data has to be taken "as-is" (binary stream) for
+	    // digest calculation, so neither content type nor charset is relevant
+	    filepart.setCharSet(data.getCharacterEncoding());
 	    
 	    Part[] parts = { xmlpart, filepart };
 
diff --git a/src/main/java/demo/SignatureCreationDemo.java b/src/main/java/demo/SignatureCreationDemo.java
index c43b45e..465a0bf 100644
--- a/src/main/java/demo/SignatureCreationDemo.java
+++ b/src/main/java/demo/SignatureCreationDemo.java
@@ -12,6 +12,7 @@ import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
 import at.gv.egiz.pdfas.api.io.DataSource;
 import at.gv.egiz.pdfas.api.sign.SignParameters;
 import at.gv.egiz.pdfas.api.sign.SignResult;
+import at.gv.egiz.pdfas.api.timestamp.DummyTimeStamper;
 import at.gv.egiz.pdfas.io.FileBasedDataSink;
 import at.gv.egiz.pdfas.io.FileBasedDataSource;
 
@@ -55,10 +56,20 @@ public class SignatureCreationDemo {
          SignParameters signParameters = new SignParameters();
          signParameters.setDocument(dataSource);
          signParameters.setOutput(dataSink);
-         signParameters.setSignatureType(Constants.SIGNATURE_TYPE_BINARY);
          signParameters.setSignatureDevice(Constants.SIGNATURE_DEVICE_MOA);
-         signParameters.setSignatureProfileId("SIGNATURBLOCK_DE");
          signParameters.setSignaturePositioning(null);
+         // standard signature
+         signParameters.setSignatureType(Constants.SIGNATURE_TYPE_TEXTUAL);
+         signParameters.setSignatureProfileId("SIGNATURBLOCK_DE");
+         
+         // --- enable in case of BAIK SIGNATURE ---
+         /*
+            signParameters.setSignatureType(Constants.SIGNATURE_TYPE_BINARY);
+            // signParameters.setSignatureProfileId("BAIK_URKUNDE_SIGNATUR");
+            signParameters.setSignatureProfileId("BAIK_ARCHIV_SIGNATUR");
+            // use BAIK TimeStamp
+            signParameters.setTimeStamperImpl(new DummyTimeStamper());
+         */
 
          // sign
          System.out.println("Signing...");
diff --git a/src/main/java/demo/SignatureVerificationDemo.java b/src/main/java/demo/SignatureVerificationDemo.java
index 6df4973..86d1bb8 100644
--- a/src/main/java/demo/SignatureVerificationDemo.java
+++ b/src/main/java/demo/SignatureVerificationDemo.java
@@ -90,15 +90,24 @@ public class SignatureVerificationDemo {
          while (it.hasNext()) {
             VerifyResult result = (VerifyResult) it.next();
             Main.formatVerifyResult(result, out);
+            
+            // check if there are timestamps
+            if (result.getTimeStampValue() != null) {
+               out.println("\nTimeStamp value available for this signature");
+            }
+            
+            // check if non textual elements have been detected for this signature
             if (result.hasNonTextualObjects()) {
-               System.out.println("\nWARNING: Non textual objects detected.");
+               out.println("\nWARNING: Non textual objects detected for this signature");
                Iterator noit = result.getNonTextualObjects().iterator();
                while (noit.hasNext()) {
                   NonTextObjectInfo info = (NonTextObjectInfo) noit.next();
-                  System.out.println("  -> " + info.toString());
+                  out.println("  -> " + info.toString());
                }
-               System.out.println();
+               out.println();
                
+            } else {
+               out.println("\nNo non-textual objects detected for this signature.");
             }
          }
          out.flush();         
diff --git a/src/main/resources/config/help_text.properties b/src/main/resources/config/help_text.properties
index 12b240c..96823ef 100644
--- a/src/main/resources/config/help_text.properties
+++ b/src/main/resources/config/help_text.properties
@@ -34,6 +34,7 @@ error.code.227=Der angegebene Wert f
 error.code.228=Der angegebene Wert f�r die x-Position in der absoluten Position darf nicht kleiner gleich 0 sein.
 error.code.229=Der angegebene Wert f�r die y-Position in der absoluten Position darf nicht kleiner gleich 0 sein.
 error.code.230=Die Schriftart konnte nicht geladen werden.
+error.code.231=Das Dokument kann nicht signiert werden, da es gesch�tzt ist.
 
 error.code.250=Das angegebene Dokument ist leer.
 error.code.251=Das angegebene Dokument enth�lt keinen extrahierbaren Text. Falls sich der Inhalt ausschlie�lich aus Bildern zusammensetzt, wird die Verwendung einer bin�ren Signatur empfohlen.
-- 
cgit v1.2.3