From a0de2a3b2a5f4a99f280f5caebbca0d183ae109a Mon Sep 17 00:00:00 2001 From: tknall Date: Wed, 7 Feb 2007 10:08:21 +0000 Subject: Bugfix: Querformat, BKU 2.7.x, ... git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@35 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../java/at/knowcenter/wag/egov/egiz/PdfAS.java | 245 ++++++++++++++---- .../knowcenter/wag/egov/egiz/commandline/Main.java | 12 +- .../egov/egiz/framework/VerificationFilter.java | 3 +- .../framework/signators/BinarySignator_1_0_0.java | 28 +- .../framework/signators/TextualSignator_1_0_0.java | 29 +-- .../wag/egov/egiz/pdf/AbsoluteTextSignature.java | 286 +++++++++++++++++---- .../wag/egov/egiz/pdf/BinarySignature.java | 70 +++-- .../at/knowcenter/wag/egov/egiz/pdf/PDFPage.java | 34 ++- .../knowcenter/wag/egov/egiz/pdf/PDFUtilities.java | 12 +- .../wag/egov/egiz/pdf/PositioningInstruction.java | 131 ++++++++++ .../at/knowcenter/wag/egov/egiz/pdf/TablePos.java | 20 ++ .../wag/egov/egiz/sig/LocalConnector.java | 12 +- .../wag/egov/egiz/sig/SignatureObject.java | 175 +++++++++++-- .../wag/egov/egiz/sig/connectors/BKUConnector.java | 89 +++++-- .../egiz/sig/connectors/BKUPostConnection.java | 54 +++- .../egov/egiz/web/AsynchronousDataResponder.java | 21 +- .../egiz/web/AsynchronousRedirectResponder.java | 6 +- .../wag/egov/egiz/web/LocalRequestHelper.java | 9 +- .../wag/egov/egiz/web/SessionInformation.java | 3 +- .../java/com/lowagie/text/pdf/PdfDictionary.java | 16 +- 20 files changed, 984 insertions(+), 271 deletions(-) create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/pdf/PositioningInstruction.java (limited to 'src/main/java') diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java b/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java index 0987b2d..f9ab652 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java @@ -46,6 +46,7 @@ import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; import at.knowcenter.wag.egov.egiz.pdf.PDFSignatureCreation; import at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject; import at.knowcenter.wag.egov.egiz.pdf.PDFUtilities; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; import at.knowcenter.wag.egov.egiz.pdf.TablePos; @@ -57,6 +58,7 @@ import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition; import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; import at.knowcenter.wag.egov.egiz.tools.Normalizer; +import at.knowcenter.wag.exactparser.ParseDocument; import at.knowcenter.wag.exactparser.parsing.PDFUtils; import at.knowcenter.wag.exactparser.parsing.results.HeaderParseResult; @@ -152,7 +154,8 @@ public abstract class PdfAS * is not 1.4. * *

- * If strict mode is deactivated, this does simply nothing. + * Furthermore (independently of strict mode) the PDF is checked for + * parsability. *

* * @param pdf @@ -168,6 +171,15 @@ public abstract class PdfAS throw new PDFDocumentException(201, "StrictMode: The pdf version is not 1.4 or lower."); } } + try + { + ParseDocument.parseDocument(pdf); + } + catch (Exception e) + { + logger_.debug("Error while parsing Document.", e); + throw new PDFDocumentException(201, e); + } } /** @@ -232,7 +244,7 @@ public abstract class PdfAS * @throws SignatureException * F.e. * @throws SignatureTypesException - * @throws NormalizeException + * @throws NormalizeException */ public static List extractSignatureHoldersTextual(String raw_text, boolean old_style) throws PDFDocumentException, SignatureException, SignatureTypesException, NormalizeException @@ -267,7 +279,7 @@ public abstract class PdfAS * found. * @throws SignatureException * @throws SignatureTypesException - * @throws NormalizeException + * @throws NormalizeException */ public static SignatureHolder extractSignatureHolderTextual(String raw_text, boolean old_style) throws SignatureException, SignatureTypesException, NormalizeException @@ -343,7 +355,8 @@ public abstract class PdfAS end_index = cur_key.getStartIndex(); } - // this normalization is required to get rid of possible trailing newlines. + // this normalization is required to get rid of possible trailing + // newlines. String normalized_text = normalizeText(signed_text); SignatureHolder holder = new TextualSignatureHolder(normalized_text, signatureObject_); return holder; @@ -368,8 +381,6 @@ public abstract class PdfAS public static List findBlockInText(String text, SignatureTypeDefinition sig_type_def, boolean old_style) { - // FIXME[tknall]: AbsoluteTextSignature.java, method findEndOfValue(...) does not work properly for landscape documents because start_index of FoundKeys are not set correctly. - // Hint: Captions and values of landscape documents are separated with " \n" and not only with " ". Vector keys = sig_type_def.getRevertSortedKeys(); Vector captions = sig_type_def.getRevertSortedCaptions(); @@ -389,11 +400,12 @@ public abstract class PdfAS String caption = (String) captions.get(key_idx); - //int found_index = text.lastIndexOf(caption); -// we're searching for captions that start at the beginning of the line. - int found_index = text.lastIndexOf("\n" + caption) + 1; // the +1 compensates the \n - - + // int found_index = text.lastIndexOf(caption); + // we're searching for captions that start at the beginning of the line. + int found_index = text.lastIndexOf("\n" + caption) + 1; // the +1 + // compensates the + // \n + if (key.equals(SignatureTypes.SIG_ID)) { if (found_index < 0 || found_index >= last_index) @@ -453,7 +465,7 @@ public abstract class PdfAS } }); } - + /** * Sorts the FoundKeys List ascendingly according to the start indices of the * found keys (the first found key in the list will have the lowest start @@ -475,7 +487,7 @@ public abstract class PdfAS return fk0.start_index - fk1.start_index; } }); - } + } /** * Checks that the found keys are in correct order regarding SIG_ID as @@ -763,7 +775,7 @@ public abstract class PdfAS String connector) throws NormalizeException, PDFDocumentException, SignatureException { String text_to_be_verified = signature_holder.getSignedText(); - + SignatureObject so_to_be_verified = signature_holder.getSignatureObject(); if (text_to_be_verified == null) @@ -774,7 +786,7 @@ public abstract class PdfAS { throw new SignatureException(311, "Document can not be verified because the length of the text to be verified is 0. (length = " + text_to_be_verified.length() + ")"); } - + if (so_to_be_verified == null) { throw new SignatureException(312, "Document can not be verified because no signature object are set."); @@ -816,8 +828,9 @@ public abstract class PdfAS final String user_name, final String user_password) throws SignatureException, PDFDocumentException { logger_.info("User signed a document: " + user_name); - - if (text_to_sign == null) { + + if (text_to_sign == null) + { throw new SignatureException(301, "Signature can not be produced. Text is null."); } if (text_to_sign.length() <= 0) @@ -907,10 +920,10 @@ public abstract class PdfAS */ public static String extractNormalizedTextTextual(final byte[] pdf) throws PresentableException { -// ByteArrayInputStream bais = new ByteArrayInputStream(pdf); -// String raw_document_text = TextualSignature.extractTextTextual(bais); -// -// String document_text = normalizeText(raw_document_text); + // ByteArrayInputStream bais = new ByteArrayInputStream(pdf); + // String raw_document_text = TextualSignature.extractTextTextual(bais); + // + // String document_text = normalizeText(raw_document_text); return extractNormalizedTextTextual(pdf, pdf.length); } @@ -927,7 +940,8 @@ public abstract class PdfAS * @throws PresentableException * F.e. */ - public static String extractNormalizedTextTextual(final byte[] pdf, final int length) throws PresentableException + public static String extractNormalizedTextTextual(final byte[] pdf, + final int length) throws PresentableException { ByteArrayInputStream bais = new ByteArrayInputStream(pdf, 0, length); String raw_document_text = TextualSignature.extractTextTextual(bais); @@ -974,6 +988,68 @@ public abstract class PdfAS return pdf_table; } + /** + * Evalutates absolute positioning and prepares the PositioningInstruction for + * placing the table. + * + * @param pos + * The absolute positioning parameter. If null it is sought in the + * profile definition. + * @param signature_type + * The profile definition of the table to be written. + * @param pdf + * The pdf. + * @param pdf_table + * The pdf table to be written. + * @return Returns the PositioningInformation. + * @throws PDFDocumentException + * F.e. + * @throws SettingsException + * F.e. + */ + public static PositioningInstruction determineTablePositioning(TablePos pos, + String signature_type, byte[] pdf, PdfPTable pdf_table) throws PDFDocumentException, SettingsException + { + if (pos == null) + { + String pos_string = SettingsReader.getInstance().getSetting(SignatureTypes.SIG_OBJ + signature_type + ".pos", null); + if (pos_string != null) + { + pos = PdfAS.parsePositionFromPosString(pos_string); + } + } + + if (pos == null) + { + // The automatic algorithm. + return PdfAS.adjustTableAndCalculatePosition(pdf, pdf_table); + } + + if (pos.page == -2) + { + // The automatic algorithm regarding the footer. + return PdfAS.adjustTableAndCalculatePositionRegardingFooter(pdf, pdf_table, pos.footer_line); + } + + boolean make_new_page = false; + int page = pos.page; + + if (pos.page == -1) + { + // Absolute positioning on a new page. + make_new_page = true; + PdfReader reader = PdfAS.readInPdfDocument(pdf); + page = reader.getNumberOfPages() + 1; + reader = null; + } + + pdf_table.setTotalWidth(pos.width); + pdf_table.setLockedWidth(true); + + return new PositioningInstruction(make_new_page, page, pos.pos_x, pos.pos_y); + + } + /** * Sets the width of the table according to the layout of the document and * calculates the y position where the PDFPTable should be placed. @@ -986,36 +1062,88 @@ public abstract class PdfAS * @throws PDFDocumentException * F.e. */ - public static TablePos adjustTableAndCalculatePosition(final byte[] pdf, - PdfPTable pdf_table) throws PDFDocumentException + public static PositioningInstruction adjustTableAndCalculatePosition( + final byte[] pdf, PdfPTable pdf_table) throws PDFDocumentException { - TablePos pos = new TablePos(); + boolean make_new_page = false; PdfReader reader = readInPdfDocument(pdf); - Rectangle psize = reader.getPageSizeWithRotation(reader.getNumberOfPages()); + int page = reader.getNumberOfPages(); + Rectangle psize = reader.getPageSizeWithRotation(page); float page_width = psize.width(); float page_height = psize.height(); - pos.width = page_width - SIGNATURE_BORDER; - pdf_table.setTotalWidth(pos.width); + final float width = page_width - SIGNATURE_BORDER; + pdf_table.setTotalWidth(width); + pdf_table.setLockedWidth(true); + + final float pos_x = SIGNATURE_BORDER / 2; + + final float table_height = pdf_table.getTotalHeight(); + final float page_length = PDFUtilities.calculateLastPageLength(pdf, page_height); + float pos_y = page_height - page_length - SIGNATURE_MARGIN; + + if (pos_y <= table_height) + { + make_new_page = true; + page++; + + pos_y = page_height - SIGNATURE_BORDER / 2; + } + + return new PositioningInstruction(make_new_page, page, pos_x, pos_y); + } + + /** + * Sets the width of the table according to the layout of the document and + * calculates the y position where the PDFPTable should be placed. + * + *

+ * This algorithm tries to position the table between the end of the text and + * the footer line. + *

+ * + * @param pdf + * The PDF document. + * @param pdf_table + * The PDFPTable to be placed. + * @return Returns the position where the PDFPTable should be placed. + * @throws PDFDocumentException + * F.e. + */ + public static PositioningInstruction adjustTableAndCalculatePositionRegardingFooter( + final byte[] pdf, PdfPTable pdf_table, float footer_line) throws PDFDocumentException + { + boolean make_new_page = false; + + PdfReader reader = readInPdfDocument(pdf); + + int page = reader.getNumberOfPages(); + Rectangle psize = reader.getPageSizeWithRotation(page); + float page_width = psize.width(); + float page_height = psize.height(); + + final float width = page_width - SIGNATURE_BORDER; + pdf_table.setTotalWidth(width); pdf_table.setLockedWidth(true); - pos.pos_x = SIGNATURE_BORDER / 2; + final float pos_x = SIGNATURE_BORDER / 2; + + final float table_height = pdf_table.getTotalHeight(); - float table_height = pdf_table.getTotalHeight(); - float page_length = PDFUtilities.calculateLastPageLength(pdf); - pos.pos_y = page_height - page_length - SIGNATURE_MARGIN; + final float page_length = PDFUtilities.calculateLastPageLength(pdf, page_height - footer_line); + float pos_y = page_height - page_length - SIGNATURE_MARGIN; - pos.page = reader.getNumberOfPages(); - if (pos.pos_y <= table_height) + if (pos_y - footer_line <= table_height) { - pos.page = -1; - // negative means to add a new page - pos.pos_y = page_height - SIGNATURE_BORDER / 2; + make_new_page = true; + page++; + + pos_y = page_height - SIGNATURE_BORDER / 2; } - return pos; + return new PositioningInstruction(make_new_page, page, pos_x, pos_y); } /** @@ -1055,27 +1183,46 @@ public abstract class PdfAS public static TablePos parsePositionFromPosString(String pos_string) throws PDFDocumentException { String[] strs = pos_string.split(";"); - if (strs.length != 4) - { - throw new PDFDocumentException(224, "Pos string (=" + pos_string + ") is invalid."); - } try { TablePos pos = new TablePos(); pos.page = Integer.parseInt(strs[0]); - pos.pos_x = Float.parseFloat(strs[1]); - pos.pos_y = Float.parseFloat(strs[2]); - pos.width = Float.parseFloat(strs[3]); - if (pos.page < 1 && pos.page != -1) + if (pos.page < 1 && pos.page != -1 && pos.page != -2) { - throw new PDFDocumentException(225, "pos.page (=" + pos.page + ") must not be lower than -1 and must not be 0."); + throw new PDFDocumentException(225, "Page (=" + pos.page + ") must not be lower than -2 and must not be 0."); } - if (pos.width <= 0.0f) + if (pos.page == -2) { - throw new PDFDocumentException(226, "pos.width (=" + pos.width + ") must not be lower or equal 0."); + if (strs.length != 2) + { + throw new PDFDocumentException(224, "Pos string (=" + pos_string + ") is invalid."); + } + + pos.footer_line = Float.parseFloat(strs[1]); + } + else + { + if (strs.length != 4) + { + throw new PDFDocumentException(224, "Pos string (=" + pos_string + ") is invalid."); + } + + pos.pos_x = Float.parseFloat(strs[1]); + pos.pos_y = Float.parseFloat(strs[2]); + pos.width = Float.parseFloat(strs[3]); + + if (pos.page < 1 && pos.page != -1) + { + throw new PDFDocumentException(225, "pos.page (=" + pos.page + ") must not be lower than -1 and must not be 0."); + } + + if (pos.width <= 0.0f) + { + throw new PDFDocumentException(226, "pos.width (=" + pos.width + ") must not be lower or equal 0."); + } } return pos; diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java b/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java index 7f5242b..bcfb6b4 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java @@ -753,21 +753,19 @@ public abstract class Main writer.println(" " + type + " ... " + (type.equals(default_type) ? "(default) " : "") + type_descr); } - writer.println(" " + PARAMETER_USER_NAME + " ... the user name"); - writer.println(" " + PARAMETER_USER_PASSWORD + " ... the user password"); + writer.println(" " + PARAMETER_USER_NAME + " ... [optional] the user name"); + writer.println(" " + PARAMETER_USER_PASSWORD + " ... [optional] the user password"); - writer.println(" " + PARAMETER_POS + " ... [optional] the absolute position of the signature block"); - writer.println(" position has the format ;;;"); - writer.println(" ... e.g. -pos=1;20.0;400.0;500.0"); + writer.println(" " + PARAMETER_POS + " ... [optional] the position of the signature block"); + writer.println(" position has the format ;;; or -2;"); writer.println(" OPTIONS for verification:"); writer.println(" " + PARAMETER_VERIFY_WHICH + " ... [optional] zero based number of the signature"); writer.println(" to be verified. If omitted, all signatures are verified."); writer.println(" Example usage:"); - writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_SIGN + " " + PARAMETER_CONNECTOR + " moa " + PARAMETER_USER_NAME + " name " + PARAMETER_USER_PASSWORD + " pwd some_document.pdf"); + writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_SIGN + " " + PARAMETER_CONNECTOR + " moa some_document.pdf"); writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_VERIFY + " some_document.pdf_out.pdf"); - } /** diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/framework/VerificationFilter.java b/src/main/java/at/knowcenter/wag/egov/egiz/framework/VerificationFilter.java index dd7a742..26f46e8 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/framework/VerificationFilter.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/framework/VerificationFilter.java @@ -107,7 +107,8 @@ public class VerificationFilter } catch (Exception e) { - throw new PDFDocumentException(201); + logger_.debug("Error while parsing Document.", e); + throw new PDFDocumentException(201, e); } // for (int i = 0; i < blocks.size(); i++) diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java b/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java index d28ac3b..6f167c8 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java @@ -22,11 +22,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import com.lowagie.text.pdf.PdfPTable; - import at.knowcenter.wag.egov.egiz.PdfAS; import at.knowcenter.wag.egov.egiz.PdfASID; -import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; import at.knowcenter.wag.egov.egiz.framework.SignResult; @@ -34,6 +31,7 @@ import at.knowcenter.wag.egov.egiz.framework.Signator; import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; import at.knowcenter.wag.egov.egiz.pdf.BinarySignature; import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; import at.knowcenter.wag.egov.egiz.pdf.ReplaceInfo; import at.knowcenter.wag.egov.egiz.pdf.StringInfo; import at.knowcenter.wag.egov.egiz.pdf.TablePos; @@ -42,6 +40,8 @@ import at.knowcenter.wag.egov.egiz.sig.SignatureObject; import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; import at.knowcenter.wag.exactparser.ByteArrayUtils; +import com.lowagie.text.pdf.PdfPTable; + /** * Signs the document binary. * @@ -90,25 +90,7 @@ public class BinarySignator_1_0_0 implements Signator PdfPTable pdf_table = PdfAS.createPdfPTableFromSignatureObject(signature_object); - if (pos == null) - { - String pos_string = SettingsReader.getInstance().getSetting(SignatureTypes.SIG_OBJ + signature_type + ".pos", null); - if (pos_string != null) - { - pos = PdfAS.parsePositionFromPosString(pos_string); - pdf_table.setTotalWidth(pos.width); - pdf_table.setLockedWidth(true); - } - else - { - pos = PdfAS.adjustTableAndCalculatePosition(pdf, pdf_table); - } - } - else - { - pdf_table.setTotalWidth(pos.width); - pdf_table.setLockedWidth(true); - } + PositioningInstruction pi = PdfAS.determineTablePositioning(pos, signature_type, pdf, pdf_table); List all_field_definitions = signature_object.getSignatureTypeDefinition().getFieldDefinitions(); List variable_field_definitions = new ArrayList(); @@ -124,7 +106,7 @@ public class BinarySignator_1_0_0 implements Signator variable_field_definitions.add(sfd); } } - IncrementalUpdateInformation iui = BinarySignature.writeIncrementalUpdate(pdf, pdf_table, pos, variable_field_definitions, all_field_definitions); + IncrementalUpdateInformation iui = BinarySignature.writeIncrementalUpdate(pdf, pdf_table, pi, variable_field_definitions, all_field_definitions); String temp_string = iui.temp_ir_number + " " + iui.temp_ir_generation + " obj"; byte[] temp_bytes = temp_string.getBytes("US-ASCII"); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_0_0.java b/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_0_0.java index 6e605ff..8cdcf63 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_0_0.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_0_0.java @@ -17,19 +17,18 @@ */ package at.knowcenter.wag.egov.egiz.framework.signators; -import com.lowagie.text.pdf.PdfPTable; - import at.knowcenter.wag.egov.egiz.PdfAS; import at.knowcenter.wag.egov.egiz.PdfASID; -import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; import at.knowcenter.wag.egov.egiz.framework.SignResult; import at.knowcenter.wag.egov.egiz.framework.Signator; import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; import at.knowcenter.wag.egov.egiz.pdf.BinarySignature; import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; import at.knowcenter.wag.egov.egiz.pdf.TablePos; -import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; + +import com.lowagie.text.pdf.PdfPTable; /** * Signs a document textually. @@ -93,27 +92,9 @@ public class TextualSignator_1_0_0 implements Signator PdfPTable pdf_table = PdfAS.createPdfPTableFromSignatureObject(iui.signed_signature_object); - if (iui.pos == null) - { - String pos_string = SettingsReader.getInstance().getSetting(SignatureTypes.SIG_OBJ + iui.signature_type + ".pos", null); - if (pos_string != null) - { - iui.pos = PdfAS.parsePositionFromPosString(pos_string); - pdf_table.setTotalWidth(iui.pos.width); - pdf_table.setLockedWidth(true); - } - else - { - iui.pos = PdfAS.adjustTableAndCalculatePosition(iui.original_document, pdf_table); - } - } - else - { - pdf_table.setTotalWidth(iui.pos.width); - pdf_table.setLockedWidth(true); - } + PositioningInstruction pi = PdfAS.determineTablePositioning(iui.pos, iui.signature_type, iui.original_document, pdf_table); - IncrementalUpdateInformation signed_iui = BinarySignature.writeIncrementalUpdate(iui.original_document, pdf_table, iui.pos, null, null); + IncrementalUpdateInformation signed_iui = BinarySignature.writeIncrementalUpdate(iui.original_document, pdf_table, pi, null, null); SignResult sign_result = new SignResult(PdfAS.PDF_MIME_TYPE, signed_iui.signed_pdf); return sign_result; diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java index b3c2e24..85673b5 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java @@ -151,69 +151,89 @@ public class AbsoluteTextSignature SignatureTypes sig_types = SignatureTypes.getInstance(); List signatureTypes_ = sig_types.getSignatureTypeDefinitions(); - List found_candidates = new ArrayList(); + List found_potential_candidates = new ArrayList(); for (int i = 0; i < signatureTypes_.size(); i++) { SignatureTypeDefinition block_type = (SignatureTypeDefinition) signatureTypes_.get(i); List found_candidates_for_type = findPotentialSignaturesForProfile(text, block_type); - found_candidates.addAll(found_candidates_for_type); + found_potential_candidates.addAll(found_candidates_for_type); } - if (found_candidates.isEmpty()) + if (found_potential_candidates.isEmpty()) { logger.debug("no candidates found at all"); return null; } + List found_candidates = new ArrayList(); logger.debug("checking block integrity"); - for (int i = 0; i < found_candidates.size(); i++) + for (int i = 0; i < found_potential_candidates.size(); i++) { - FoundBlock found_block = (FoundBlock) found_candidates.get(i); + FoundBlock found_block = (FoundBlock) found_potential_candidates.get(i); String date_value = getDateValue(text, found_block); logger.debug("date_value = " + date_value); - EGIZDate date = EGIZDate.parseFromString(date_value); + try + { + EGIZDate date = EGIZDate.parseFromString(date_value); + + logger.debug("found_block = " + date + " - " + found_block); - logger.debug("found_block = " + date + " - " + found_block); + checkBlockIntegrity(text, found_block); - checkBlockIntegrity(text, found_block); + found_candidates.add(found_block); + } + catch (Exception e) + { + logger.debug("Exception while checking the integrity of the found block " + found_block + ". Ignoring this block.", e); + } } sortFoundBlocksByDate(text, found_candidates); - - logger.debug("sorted blocks:"); - for (int i = 0; i < found_candidates.size(); i++) + if (logger.isDebugEnabled()) { - FoundBlock found_block = (FoundBlock) found_candidates.get(i); + logger.debug("sorted blocks:"); + for (int i = 0; i < found_candidates.size(); i++) + { + FoundBlock found_block = (FoundBlock) found_candidates.get(i); - String date_value = getDateValue(text, found_block); - EGIZDate date = EGIZDate.parseFromString(date_value); + String date_value = getDateValue(text, found_block); + EGIZDate date = EGIZDate.parseFromString(date_value); - logger.debug(" #" + i + ": " + date + " - " + found_block); + logger.debug(" #" + i + ": " + date + " - " + found_block); + } } List latest_blocks = filterLastDateEqualBlocks(text, found_candidates); - logger.debug("latest blocks:"); - for (int i = 0; i < latest_blocks.size(); i++) + if (logger.isDebugEnabled()) { - FoundBlock found_block = (FoundBlock) latest_blocks.get(i); + logger.debug("latest blocks:"); + for (int i = 0; i < latest_blocks.size(); i++) + { + FoundBlock found_block = (FoundBlock) latest_blocks.get(i); - String date_value = getDateValue(text, found_block); - EGIZDate date = EGIZDate.parseFromString(date_value); + String date_value = getDateValue(text, found_block); + EGIZDate date = EGIZDate.parseFromString(date_value); - logger.debug(" #" + i + ": " + date + " - " + found_block); + logger.debug(" #" + i + ": " + date + " - " + found_block); + } } - boolean semantic_equality = PdfAS.checkForSemanticEquality(latest_blocks); - logger.debug("semantic_equality = " + semantic_equality); - if (!semantic_equality) - { - throw new SignatureException(314, "The latest blocks weren't semantically equal."); - } + // The semantic equality check has been outdated by the + // advanced choosing algorithm. + // boolean semantic_equality = + // PdfAS.checkForSemanticEquality(latest_blocks); + // logger.debug("semantic_equality = " + semantic_equality); + // if (!semantic_equality) + // { + // throw new SignatureException(314, "The latest blocks weren't semantically + // equal."); + // } + + FoundBlock latest_block = chooseMostPossibleBlock(latest_blocks); - FoundBlock latest_block = chooseMostPossibleSemanticallyEqualBlock(latest_blocks); logger.debug("latest block = " + latest_block); return latest_block; } @@ -269,7 +289,6 @@ public class AbsoluteTextSignature } } - for (int lci = 0; lci < found_last_captions.size(); lci++) { int last_caption_index = ((Integer) found_last_captions.get(lci)).intValue(); @@ -470,8 +489,6 @@ public class AbsoluteTextSignature */ public static int findEndOfValue(String text, int start_index) { - // FIXME[tknall]: this method does not work properly for landscape documents because always starts with "\n". Look for errors in PdfAS.java, method findBlockInText(...) to set the start_index accordingly. - // Hint: Captions and values of landscape documents are separated with " \n" and not only with " ". int newline_index = text.indexOf('\n', start_index); if (newline_index < 0) { @@ -685,44 +702,213 @@ public class AbsoluteTextSignature } /** - * Chooses the most possible (best choice) block of the list of semantically - * equal blocks. + * Chooses the most possible (best choice) block of the list of blocks. * *

- * Thus blocks are considered semantically equal if their required keys are - * semantically equal, semantically equal blocks may still differ in the - * number of their non required fields. This may lead to multiple found blocks - * of the same size in characters, but where some blocks' elements swallow - * elements found by other blocks. + * The strategy to find the most possible block is to choose the very one + * block with the maximum number of captions. This block has extracted most + * information from the text. *

*

- * The strategy to avoid this is to choose the very one block with the maximum - * number of captions. This block has extracted most information from the - * text. + * If there are still multiple blocks with the same number of cations, the + * blocks are compared caption-wise. The block with all captions being longer + * or equal to all other blocks' captions wins. *

* * @param found_blocks * The List of semantically equal blocks. * @return Returns the best choice FoundBlock. + * @throws SignatureException + */ + public static FoundBlock chooseMostPossibleBlock(List found_blocks) throws SignatureException + { + // int largest_block_index = 0; + // FoundBlock largest_block = (FoundBlock) found_blocks.get(0); + // + // for (int i = 1; i < found_blocks.size(); i++) + // { + // FoundBlock current_block = (FoundBlock) found_blocks.get(i); + // + // if (current_block.found_keys.size() > largest_block.found_keys.size()) + // { + // largest_block = current_block; + // largest_block_index = i; + // } + // } + + List vertically_largest = filterVerticallyLargestBlocks(found_blocks); + if (logger.isDebugEnabled()) + { + logger.debug("vertically largest blocks:"); + for (int i = 0; i < vertically_largest.size(); i++) + { + FoundBlock found_block = (FoundBlock) vertically_largest.get(i); + + logger.debug(" #" + i + ": " + found_block); + } + } + + List horizontally_largest = filterHorizontallyLargestBlocks(vertically_largest); + if (logger.isDebugEnabled()) + { + logger.debug("horizontally largest blocks:"); + for (int i = 0; i < horizontally_largest.size(); i++) + { + FoundBlock found_block = (FoundBlock) horizontally_largest.get(i); + + logger.debug(" #" + i + ": " + found_block); + } + } + + FoundBlock largest_block = (FoundBlock) horizontally_largest.get(0); + + logger.debug("Chose largest block: " + largest_block); + return largest_block; + } + + /** + * Filters out all blocks but the vertically largest ones. + * + *

+ * A vertically largest block has the most found keys. + *

+ * + * @param found_blocks + * The List of FoundBlock objects to be filtered. + * @return Returns the List of the vertically largest FoundBlock objects. */ - public static FoundBlock chooseMostPossibleSemanticallyEqualBlock( - List found_blocks) + public static List filterVerticallyLargestBlocks(List found_blocks) { - int largest_block_index = 0; + // determine the size of the largest block(s) + int largest_size = Integer.MIN_VALUE; + for (int i = 1; i < found_blocks.size(); i++) + { + FoundBlock fb = (FoundBlock) found_blocks.get(i); + final int current_size = fb.found_keys.size(); + if (current_size > largest_size) + { + largest_size = current_size; + } + } + + // keep all blocks that have the largest_size + List largest_blocks = new ArrayList(); + for (int i = 0; i < found_blocks.size(); i++) + { + FoundBlock fb = (FoundBlock) found_blocks.get(i); + if (fb.found_keys.size() < largest_size) + { + continue; + } + largest_blocks.add(fb); + } + + return largest_blocks; + } + + /** + * Filters out all blocks but the horizonally largest ones. + * + *

+ * A vertically largest block has the most found keys. + *

+ * + * @param found_blocks + * The List of FoundBlock objects to be filtered. All of these + * FoundBlock objects must have the same number of found keys. + * @return Returns the List of the horizontally largest FoundBlock objects. + * @throws SignatureException + */ + public static List filterHorizontallyLargestBlocks(List found_blocks) throws SignatureException + { + List horizontally_largest = new ArrayList(); FoundBlock largest_block = (FoundBlock) found_blocks.get(0); + horizontally_largest.add(largest_block); for (int i = 1; i < found_blocks.size(); i++) { - FoundBlock current_block = (FoundBlock) found_blocks.get(i); + FoundBlock fb = (FoundBlock) found_blocks.get(i); + + if (isHorizontallyEqual(fb, largest_block)) + { + horizontally_largest.add(fb); + continue; + } - if (current_block.found_keys.size() > largest_block.found_keys.size()) + if (isHorizontallyLarger(fb, largest_block)) + { + horizontally_largest = new ArrayList(); + largest_block = fb; + horizontally_largest.add(largest_block); + } + else { - largest_block = current_block; - largest_block_index = i; + if (!isHorizontallyLarger(largest_block, fb)) + { + // The block is neither equal nor larger nor lower. + // We cannot exactly determine which one to use. + throw new SignatureException(315, "The blocks are neither larger nor lower nor equal. Cannot decide which one to pick. fb = " + fb + ", largest_block = " + largest_block); + } } + } - logger.debug("Chose largest block with index #" + largest_block_index + ": " + largest_block); - return largest_block; + return horizontally_largest; } + + protected static boolean isHorizontallyEqual(FoundBlock fb0, FoundBlock fb1) + { + final int num_keys = fb0.found_keys.size(); + if (num_keys != fb1.found_keys.size()) + { + throw new IllegalArgumentException("Cannot compare FoundBlock keys: fb0 doesn't have the same number of keys as fb1. " + fb0.found_keys.size() + " vs. " + fb1.found_keys.size()); + } + + for (int i = 0; i < num_keys; i++) + { + FoundKey fk0 = (FoundKey) fb0.found_keys.get(i); + FoundKey fk1 = (FoundKey) fb1.found_keys.get(i); + + if (fk0.caption.length() != fk1.caption.length()) + { + return false; + } + } + + return true; + } + + protected static boolean isHorizontallyLarger(FoundBlock fb0, FoundBlock fb1) + { + final int num_keys = fb0.found_keys.size(); + if (num_keys != fb1.found_keys.size()) + { + throw new IllegalArgumentException("Cannot compare FoundBlock keys: fb0 doesn't have the same number of keys as fb1. " + fb0.found_keys.size() + " vs. " + fb1.found_keys.size()); + } + + boolean larger = false; + + for (int i = 0; i < num_keys; i++) + { + FoundKey fk0 = (FoundKey) fb0.found_keys.get(i); + FoundKey fk1 = (FoundKey) fb1.found_keys.get(i); + + if (fk0.caption.length() == fk1.caption.length()) + { + continue; + } + + if (fk0.caption.length() > fk1.caption.length()) + { + larger = true; + continue; + } + + // if (fk0.caption.length() < fk1.caption.length()) + return false; + } + + return larger; + } + } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java index c5acbc4..e10061c 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java @@ -667,17 +667,15 @@ public abstract class BinarySignature * The original document. * @param pdf_table * The PdfPTable that contains the signature block. - * @param pos - * The Position object giving the exact location where to place the - * table. if page is -1, a new page will be appended to the document. - * Then the table will be inserted on that new page using the - * coordinates. + * @param pi + * The PositioningInstruction telling the algorithm where to place + * the signature block. * @return Returns the new document. * @throws PresentableException * Forwarded exception. */ public static IncrementalUpdateInformation writeIncrementalUpdate( - byte[] original_document, PdfPTable pdf_table, TablePos pos, + byte[] original_document, PdfPTable pdf_table, PositioningInstruction pi, List variable_field_definitions, List all_field_definitions) throws PresentableException { try @@ -697,30 +695,20 @@ public abstract class BinarySignature // The stamper allows this by setting append = true PdfStamper stamper = new PdfStamper(reader, baos, '\0', true); - int pdf_page_num = reader.getNumberOfPages(); - - // int signature_page = -1; - // - // if (pos_y >= 0) - // { - // signature_page = pdf_page_num; - // } - if (pos.page == -1) + if (pi.isMakeNewPage()) { - pos.page = pdf_page_num + 1; + int pdf_page_num = reader.getNumberOfPages(); Rectangle psize = reader.getPageSizeWithRotation(pdf_page_num); Rectangle rect = new Rectangle(psize); - stamper.insertPage(pos.page, rect); - - // pos_y *= -1; + stamper.insertPage(pdf_page_num + 1, rect); } - if (pos.page < 1 || pos.page > stamper.getReader().getNumberOfPages()) + if (pi.getPage() < 1 || pi.getPage() > stamper.getReader().getNumberOfPages()) { - throw new PDFDocumentException(224, "The provided pos.page (=" + pos.page + ") is out of range."); + throw new PDFDocumentException(224, "The provided page (=" + pi.getPage() + ") is out of range."); } - PdfContentByte content = stamper.getOverContent(pos.page); + PdfContentByte content = stamper.getOverContent(pi.getPage()); // content = StampContent einer PageStamp. // System.out.println("table_width = " + pdf_table.getTotalWidth() + ", @@ -741,27 +729,27 @@ public abstract class BinarySignature // pdf_table.writeSelectedRows(0, -1, SIGNATURE_BORDER / 2, // table_position, content); - content.addTemplate(table_template, pos.pos_x, pos.pos_y - pdf_table.getTotalHeight()); + content.addTemplate(table_template, pi.getX(), pi.getY() - pdf_table.getTotalHeight()); // For debugging print a 100x100 grid -// { -// Rectangle psize = reader.getPageSizeWithRotation(pos.page); -// float page_width = psize.width(); -// float page_height = psize.height(); -// for (float x = 0; x < page_width; x += 100) -// { -// content.moveTo(x, 0); -// content.lineTo(x, page_height); -// content.stroke(); -// } -// for (float y = 0; y < page_height; y += 100) -// { -// content.moveTo(0, y); -// content.lineTo(page_width, y); -// content.stroke(); -// } -// } - + // { + // Rectangle psize = reader.getPageSizeWithRotation(pos.page); + // float page_width = psize.width(); + // float page_height = psize.height(); + // for (float x = 0; x < page_width; x += 100) + // { + // content.moveTo(x, 0); + // content.lineTo(x, page_height); + // content.stroke(); + // } + // for (float y = 0; y < page_height; y += 100) + // { + // content.moveTo(0, y); + // content.lineTo(page_width, y); + // content.stroke(); + // } + // } + // content.setLineWidth(10.0f); // content.moveTo(0, 0); // content.lineTo(100, 100); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java index c98aee8..c1d6681 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java @@ -66,14 +66,23 @@ public class PDFPage extends PDFTextStripper protected float max_image_ypos = Float.NEGATIVE_INFINITY; /** - * The empty constructor. + * The y coordinate of the footer line. PDF elements below this footer line will not be regarded. + */ + protected float footer_line = 0.0f; + + /** + * Constructor. + * + * @param footer_line The y coordinate of the footer line. PDF elements below this footer line will not be regarded. * * @throws IOException */ - public PDFPage() throws IOException + public PDFPage(float footer_line) throws IOException { super(); + this.footer_line = footer_line; + OperatorProcessor newInvoke = new MyInvoke(); newInvoke.setContext(this); operators.put("Do", newInvoke); @@ -341,17 +350,24 @@ public class PDFPage extends PDFTextStripper */ protected void showCharacter(TextPosition text) { - float current_y = text.getY(); - String character = text.getCharacter(); + final float current_y = text.getY(); + final String character = text.getCharacter(); + +// if (current_y > this.footer_line) +// { +// logger_.debug("character is below footer_line. footer_line = " + this.footer_line + ", text.character=" + character + ", y=" + current_y); +// return; +// } + // store ypos of the char if it is not empty if (!character.equals(" ") && current_y > this.max_character_ypos) { this.max_character_ypos = current_y; - //logger_.debug("text.character=" + character + ", y=" + current_y); + logger_.debug("text.character=" + character + ", y=" + current_y); // System.err.println(character + "|" + current_y); } - // logger_.debug("text.character=" + character + ", y=" + current_y); + logger_.debug("text.character=" + character + ", y=" + current_y); // System.err.println(character + "|" + current_y); } @@ -454,6 +470,12 @@ public class PDFPage extends PDFTextStripper logger_.debug("actual_lowest_point = " + actual_lowest_point); + if (actual_lowest_point > PDFPage.this.footer_line) + { + logger_.debug("image is below footer_line. footer_line = " + PDFPage.this.footer_line); + return; + } + if (actual_lowest_point > PDFPage.this.max_image_ypos) { PDFPage.this.max_image_ypos = actual_lowest_point; diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java index 8fa3b35..05854dd 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java @@ -38,7 +38,7 @@ import com.lowagie.text.DocumentException; */ public abstract class PDFUtilities { - public static float calculateLastPageLength(final byte[] pdf) throws PDFDocumentException + public static float calculateLastPageLength(final byte[] pdf, float footer_line) throws PDFDocumentException { try { @@ -53,7 +53,7 @@ public abstract class PDFUtilities parser.parse(); PDDocument pdfDocument_ = parser.getPDDocument(); - float last_page_length = calculateLastPageLength(pdfDocument_); + float last_page_length = calculateLastPageLength(pdfDocument_, footer_line); pdfDocument_.close(); return last_page_length; @@ -68,20 +68,20 @@ public abstract class PDFUtilities } } - public static float calculateLastPageLength(PDDocument document) throws IOException + public static float calculateLastPageLength(PDDocument document, float footer_line) throws IOException { int last_page_id = document.getNumberOfPages(); List allPages = document.getDocumentCatalog().getAllPages(); PDPage last_page = (PDPage) allPages.get(last_page_id - 1); - return calculatePageLength(last_page); + return calculatePageLength(last_page, footer_line); } - public static float calculatePageLength(PDPage page) throws IOException + public static float calculatePageLength(PDPage page, float footer_line) throws IOException { // logger_.debug("Last Page id:" + last_page_id); // PDPage last_page = (PDPage) allPages.get(0); - PDFPage my_page = new PDFPage(); + PDFPage my_page = new PDFPage(footer_line); my_page.processStream(page, page.findResources(), page.getContents().getStream()); return my_page.getMaxPageLength(); } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PositioningInstruction.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PositioningInstruction.java new file mode 100644 index 0000000..c04177b --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PositioningInstruction.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2006 by Know-Center, Graz, Austria + * + * This software is the confidential and proprietary information of Know-Center, + * Graz, Austria. You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement you entered + * into with Know-Center. + * + * KNOW-CENTER MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF + * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR + * NON-INFRINGEMENT. KNOW-CENTER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY + * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. + * + * $Id: $ + */ +package at.knowcenter.wag.egov.egiz.pdf; + +/** + * The positioning instruction holds information of where to place the signature + * block. + * + *

+ * This instruction is given to the PDF writer in order to place the signature. + *

+ * + * @author wprinz + */ +public class PositioningInstruction +{ + + /** + * Tells, if a new plain page should be appended. + * + *

+ * This command is executed before the signature block is positioned according + * to page, x and y. + *

+ */ + protected boolean make_new_page = false; + + /** + * The number of the page on which the signature block is to be placed. If + * specified to make a new page, the number of this newly created page can be + * used here as well. + */ + protected int page = 0; + + /** + * The x coordinate where the upper left corner of the signature block should + * be placed. + */ + protected float x = 0.0f; + + /** + * The y coordinate where the upper left corner of the signature block should + * be placed. + */ + protected float y = 0.0f; + + /** + * + * @param make_new_page + * Tells, if a new plain page should be appended. This command is + * executed before the signature block is positioned according to + * page, x and y. + * @param page + * The number of the page on which the signature block is to be + * placed. If specified to make a new page, the number of this newly + * created page can be used here as well. + * @param x + * The x coordinate where the upper left corner of the signature + * block should be placed. + * @param y + * The y coordinate where the upper left corner of the signature + * block should be placed. + */ + public PositioningInstruction(boolean make_new_page, int page, float x, float y) + { + this.make_new_page = make_new_page; + this.page = page; + this.x = x; + this.y = y; + } + + /** + * Tells, if a new plain page should be appended to the document. + * + * @return Returns true, if a new plain page should be appended. + */ + public boolean isMakeNewPage() + { + return this.make_new_page; + } + + /** + * Returns the page on which the signature is to be printed. + * + * @return Returns the page on which the signature is to be printed. + */ + public int getPage() + { + return this.page; + } + + /** + * Returns the x coordinate where the upper left corner of the signature block + * should be placed. + * + * @return Returns the x coordinate where the upper left corner of the + * signature block should be placed. + */ + public float getX() + { + return this.x; + } + + /** + * Returns the y coordinate where the upper left corner of the signature block + * should be placed. + * + * @return Returns the y coordinate where the upper left corner of the + * signature block should be placed. + */ + public float getY() + { + return this.y; + } + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java index ba55cdf..6cfdded 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java @@ -35,6 +35,22 @@ public class TablePos implements Serializable /** * The page on which the block should be displayed. + * + *

+ * A value greater than or equal 1 means to absolutely position the signature + * on that page. + *

+ *

+ * A value of -1 means to append a new page to the document and absolutely + * position the signature on the new page. + *

+ *

+ * A value of -2 means to determine the length of the last page as without + * absolute positioning, but ignore all text below a certain footer line. If + * there is enough space between the end of the text and this footer line, the + * signature should be positioned automatically in there. Otherwise it should + * be placed on a new page. + *

*/ public int page = 0; @@ -53,4 +69,8 @@ public class TablePos implements Serializable */ public float width = 0.0f; + /** + * The top y position of the footer line. + */ + public float footer_line = 0.0f; } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/LocalConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/LocalConnector.java index 13e0b65..65c79a9 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/LocalConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/LocalConnector.java @@ -17,6 +17,8 @@ */ package at.knowcenter.wag.egov.egiz.sig; +import java.util.Properties; + import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; /** @@ -74,27 +76,25 @@ public interface LocalConnector extends Connector /** * Analyzes the sign response string. * - * @param response_string - * The response string from the local service. * @param signature_type * The type of the signature. * @return Returns the SignatureObject of the sign request. * @throws SignatureException * F.e. */ - public SignatureObject analyzeSignResponse(String response_string, + // TODO hotfix + public SignatureObject analyzeSignResponse(Properties response_properties, String signature_type) throws SignatureException; /** * Analyzes the verify response string. * - * @param response_string - * The response string from the local service. * @return Returns the SignatureResponse of the verify request. * @throws SignatureException * F.e. */ - public SignatureResponse analyzeVerifyResponse(String response_string) throws SignatureException; + // TODO hotfix + public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws SignatureException; /** * Returns the sign URL of the local service. diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java index 9a7a036..ae50c5e 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java @@ -31,6 +31,7 @@ import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; import java.util.Vector; @@ -41,13 +42,14 @@ import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger; import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException; import at.knowcenter.wag.egov.egiz.exceptions.NormalizeException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException; -import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; import at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIException; import at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIFactory; import at.knowcenter.wag.egov.egiz.ldap.client.LDAPIssuerNameFilter; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; import at.knowcenter.wag.egov.egiz.table.Entry; import at.knowcenter.wag.egov.egiz.table.Style; import at.knowcenter.wag.egov.egiz.table.Table; @@ -181,7 +183,7 @@ public class SignatureObject implements Serializable *

*/ protected String raw_signature_response = null; - + /** * Filters the issuer name in order to find matches. * @author tknall @@ -199,8 +201,6 @@ public class SignatureObject implements Serializable } }; - - /** * The empty constructor. It initilize the normlizer, load the settings and * set the default styles. @@ -270,7 +270,6 @@ public class SignatureObject implements Serializable defaultImageStyle_.setPadding(3); defaultImageStyle_.setHAlign(Style.CENTER); defaultImageStyle_.setVAlign(Style.MIDDLE); -// defaultImageStyle_.setBgColor(new Color(255, 255, 255)); defaultImageStyle_.setBgColor(null); defaultCaptionStyle_.setHAlign(Style.CENTER); @@ -737,20 +736,42 @@ public class SignatureObject implements Serializable setSigValue(SignatureTypes.SIG_ID, sigIds); } - /** - * Set the signation id's build by a BKU signated SignatureObject. - * - * @param sigIds - * The sination id's are defined into five parts, that have the same - * base as prefix. Therefore the ids's are reduced by the base prefix - * and stored in the SignatureObject. - */ - public void setSignationIDs(String[] sigIds) + // /** + // * Set the signation id's build by a BKU signated SignatureObject. + // * + // * @param sigIds + // * The sination id's are defined into five parts, that have the same + // * base as prefix. Therefore the ids's are reduced by the base prefix + // * and stored in the SignatureObject. + // */ + // public void setSignationIDs(String[] sigIds) + // { + // String join = ""; + // String base = null; + // for (int arr_idx = 0; arr_idx < sigIds.length; arr_idx++) + // { + // String id = sigIds[arr_idx]; + // if (logger_.isDebugEnabled()) + // { + // logger_.debug("Set BKU id:" + id); + // } + // int id_idx = id.lastIndexOf("-"); + // if (arr_idx == 0) + // { + // base = id.substring(0, id_idx); + // } + // String cur_id = id.substring(id_idx + 1); + // join += "-" + cur_id; + // } + // setSignationIDs(base + "@" + join.substring(1)); + // } + + // TODO hotfix + public static String formatSigIds(Properties response_properties, + String[] sigIds) throws SignatureException { - - // FIXME[tknall]: implement workaround resp. failsafe behaviour for ids like "Signature-123456789" - - String join = ""; + // ids algorithm: + String join = ""; String base = null; for (int arr_idx = 0; arr_idx < sigIds.length; arr_idx++) { @@ -767,7 +788,47 @@ public class SignatureObject implements Serializable String cur_id = id.substring(id_idx + 1); join += "-" + cur_id; } - setSignationIDs(base + "@" + join.substring(1)); + // setSignationIDs(base + "@" + join.substring(1)); + String ids = base + "@" + join.substring(1); + // :ids algorithm + + String productName = response_properties.getProperty("productName"); + logger_.debug("productName = " + productName); + if (!productName.equals("trustDeskbasic")) + { + final String msg = "The BKU environment " + productName + " is not trustDeskbasic and therefore the productVersion cannot be decided."; + logger_.error(msg); + throw new SignatureException(0, msg); + } + + String productVersion = response_properties.getProperty("productVersion"); + logger_.debug("productVersion = " + productVersion); + boolean new_etsi = decideNewEtsiByBKUVersion(productVersion); + logger_.debug("verwende neue etsi properties = " + new_etsi); + + String etsi_prefix = ""; + if (new_etsi) + { + // TODO hotfix + etsi_prefix = "etsi-bka-1.0@"; + } + + String final_ids = etsi_prefix + ids; + logger_.debug("final_ids = " + final_ids); + + return final_ids; + } + + // TODO hotfix + public static boolean decideNewEtsiByBKUVersion(String productVersion) + { + boolean new_etsi = true; + // TODO make better + if (productVersion.startsWith("2.5") || productVersion.startsWith("2.4") || productVersion.startsWith("2.3") || productVersion.startsWith("2.2") || productVersion.startsWith("2.1") || productVersion.startsWith("1") || productVersion.startsWith("0")) + { + new_etsi = false; + } + return new_etsi; } /** @@ -837,9 +898,51 @@ public class SignatureObject implements Serializable * * @return the id array */ - public String[] getSignationIds() + // TODO hotifx + public String getSignationIds() { String sig_ids = getSigValue(SignatureTypes.SIG_ID); + return sig_ids; + + // if (sig_ids == null || sig_ids.length() == 0) + // { + // return null; + // } + // + // // int index = sig_ids.indexOf(PdfAS.IDS); + // // if (index < 0) + // // { + // // return null; + // // } + // // sig_ids = sig_ids.substring(index + PdfAS.IDS.length()); + // // + // // if (sig_ids == null || sig_ids.length() == 0) + // // { + // // return null; + // // } + // + // String[] ids_str = sig_ids.split("@"); + // String base = ids_str[0]; + // String[] ids = ids_str[1].split("-"); + // String[] real_ids = new String[5]; + // real_ids[0] = base + "-" + ids[0]; + // real_ids[1] = "0-" + base + "-" + ids[1]; + // real_ids[2] = "0-" + base + "-" + ids[2]; + // real_ids[3] = "0-" + base + "-" + ids[3]; + // real_ids[4] = "0-" + base + "-" + ids[4]; + // if (logger_.isDebugEnabled()) + // { + // for (int id_idx = 0; id_idx < real_ids.length; id_idx++) + // { + // logger_.debug("Set BKU id:" + real_ids[id_idx]); + // } + // } + // return real_ids; + } + + // TODO hotfix + public static String[] parseSigIds(String sig_ids) + { if (sig_ids == null || sig_ids.length() == 0) { return null; @@ -858,21 +961,33 @@ public class SignatureObject implements Serializable // } String[] ids_str = sig_ids.split("@"); + + String etsi_string = null; + if (ids_str.length == 3) + { + etsi_string = ids_str[0]; + String[] rest_ids = new String[] { ids_str[1], ids_str[2] }; + ids_str = rest_ids; + } + String base = ids_str[0]; String[] ids = ids_str[1].split("-"); - String[] real_ids = new String[5]; + String[] real_ids = new String[6]; // the last one contains the etsi string real_ids[0] = base + "-" + ids[0]; real_ids[1] = "0-" + base + "-" + ids[1]; real_ids[2] = "0-" + base + "-" + ids[2]; real_ids[3] = "0-" + base + "-" + ids[3]; real_ids[4] = "0-" + base + "-" + ids[4]; + real_ids[5] = etsi_string; + if (logger_.isDebugEnabled()) { for (int id_idx = 0; id_idx < real_ids.length; id_idx++) { - logger_.debug("Set BKU id:" + real_ids[id_idx]); + logger_.debug("real_ids[" + id_idx + "] = " + real_ids[id_idx]); } } + return real_ids; } @@ -1364,6 +1479,12 @@ public class SignatureObject implements Serializable } SignatureTypes sig_types = SignatureTypes.getInstance(); signatureDefinition_ = sig_types.getSignatureTypeDefinition(sigType_); + if (signatureDefinition_ == null) + { + final String msg = "The SignatureObject's sigType '" + sigType_ + "' wasn't found in the configuration file's specified signature profiles. This usually happens if the sig_obj.type.default object has been turned off or is misspelled."; + logger_.error(msg); + throw new SignatureTypesException(msg); + } Map key_cap_map = signatureDefinition_.getKeyCaptionMap(); if (key_cap_map != null) { @@ -1409,10 +1530,10 @@ public class SignatureObject implements Serializable } } // value = new String(CodingHelper.encodeUTF8(value)); -// if (logger_.isDebugEnabled()) -// { -// logger_.debug("key:" + key + " value:" + value); -// } + // if (logger_.isDebugEnabled()) + // { + // logger_.debug("key:" + key + " value:" + value); + // } setSigValue(key, value); } } @@ -1534,6 +1655,4 @@ public class SignatureObject implements Serializable return strg; } - - } \ No newline at end of file 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 3b672f1..6327a11 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 @@ -18,6 +18,7 @@ package at.knowcenter.wag.egov.egiz.sig.connectors; import java.io.UnsupportedEncodingException; +import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -116,9 +117,9 @@ public class BKUConnector implements LocalConnector String request_string = prepareSignRequest(userName, signText, sigType); String sign_url = getSignURL(sigType); - String response_string = sendRequest(sign_url, request_string); + Properties response_properties = sendRequest(sign_url, request_string); - return analyzeSignResponse(response_string, sigType); + return analyzeSignResponse(response_properties, sigType); } /** @@ -140,9 +141,9 @@ public class BKUConnector implements LocalConnector String request_string = prepareVerifyRequest(normalizedText, sigObject); String verify_url = getVerifyURL(sigObject.getSignationType()); - String response_string = sendRequest(verify_url, request_string); + Properties response_properties = sendRequest(verify_url, request_string); - return analyzeVerifyResponse(response_string); + return analyzeVerifyResponse(response_properties); } /** @@ -162,8 +163,10 @@ public class BKUConnector implements LocalConnector * @see CodingHelper * @see X509Cert */ - private void parseCreateXMLResponse(String xmlResponse, SignatureObject sigObj) throws SignatureException + private void parseCreateXMLResponse(Properties response_properties, SignatureObject sigObj) throws SignatureException { + String xmlResponse = response_properties.getProperty("response_string"); + Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>"); Pattern sig_val_p_e = Pattern.compile(""); Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>"); @@ -266,7 +269,11 @@ public class BKUConnector implements LocalConnector ids[2] = extractId(xmlResponse, "signed-data-object-"); ids[3] = extractId(xmlResponse, "etsi-data-reference-"); ids[4] = extractId(xmlResponse, "etsi-data-object-"); - sigObj.setSignationIDs(ids); + + //TODO hotfix + String final_ids =SignatureObject.formatSigIds(response_properties, ids); + //sigObj.setSignationIDs(ids); + sigObj.setSignationIDs(final_ids); } /** @@ -283,6 +290,13 @@ public class BKUConnector implements LocalConnector String id = null; int start_idx = text.indexOf(name) + name.length(); int end_idx = text.indexOf("\"", start_idx); + + // TODO hotfix! + final int quot_end_idx = end_idx; + final int squot_end_idx = text.indexOf("'", start_idx); + end_idx = Math.min(quot_end_idx, squot_end_idx); + // TODO hotfix end! + id = text.substring(start_idx, end_idx); if (logger_.isDebugEnabled()) { @@ -324,6 +338,21 @@ public class BKUConnector implements LocalConnector String verify_template = getVerifyTemplateFileName(sigObject.getSignationType()); String sig_prop_filename = getSigPropFileName(sigObject.getSignationType()); + String ids_string = sigObject.getSignationIds(); + logger_.debug("ids_string = " + ids_string); + String[] ids = SignatureObject.parseSigIds(ids_string); + + // TODO hotfix + final boolean neue_bku = ids[5] != null; + logger_.debug("ids[5] = " + ids[5]); + logger_.debug("neue_bku = " + neue_bku); + if (neue_bku) + { + verify_template = getConnectorValueFromProfile(sigObject.getSignationType(), "bku.verify.template2"); //"./templates/BKUVerifyTemplateB64_neueBKU.xml"; + sig_prop_filename = getConnectorValueFromProfile(sigObject.getSignationType(), "bku.verify.template2.SP"); //"./templates/BKUVerifyTemplateSP_neueBKU.xml"; + } + + String ver_temp_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_template)); String sig_prop_str = FileHelper.readFromFile(SettingsReader.relocateFile(sig_prop_filename)); if (logger_.isDebugEnabled()) @@ -345,8 +374,7 @@ public class BKUConnector implements LocalConnector cert_alg = settings_.getValueFromKey("cert.alg.rsa"); } - String[] ids = sigObject.getSignationIds(); - sig_prop_str = sig_prop_str.replaceFirst("SigningTimeReplace", sigObject.getSignationDate()); + sig_prop_str = sig_prop_str.replaceFirst("SigningTimeReplace", sigObject.getSignationDate()); String issuer_name = sigObject.getSignationIssuer(); // The issuer is already unicode, so it mustn't be encoded again. @@ -362,6 +390,26 @@ public class BKUConnector implements LocalConnector ver_temp_str = ver_temp_str.replaceFirst("CertAlgReplace", cert_alg); ver_temp_str = ver_temp_str.replaceFirst("TemplateQualifyingPropertiesReplace", sig_prop_str); byte[] sig_prop_code = CodingHelper.buildDigest(sig_prop_str.getBytes("UTF-8")); + + // TODO hotfix + if (neue_bku) + { + final String ETSI_SIGNED_PROPERTIES_START_TAG = "= 0; + final int hash_end = sig_prop_str.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length(); + assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0; + assert hash_end > hash_start; + + final String string_to_be_hashed = sig_prop_str.substring(hash_start, hash_end); + logger_.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); + + final byte [] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); + sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed); + } + String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code); ver_temp_str = ver_temp_str.replaceFirst("DigestValueSignedPropertiesReplace", sig_prop_hash); if (logger_.isDebugEnabled()) @@ -445,7 +493,7 @@ public class BKUConnector implements LocalConnector Pattern cert_qualified_p = Pattern.compile(""); Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse); // [tknall] stop qualified certificate - + Pattern code_p_s = Pattern.compile(""); Pattern code_p_e = Pattern.compile(""); Pattern info_p_s = Pattern.compile(""); @@ -472,7 +520,7 @@ public class BKUConnector implements LocalConnector Matcher cert_m_e = cert_p_e.matcher(xmlResponse); SignatureResponse sig_res = new SignatureResponse(); - + // [tknall] start qualified certificate sig_res.setQualifiedCertificate(cert_qualified_m.find()); // [tknall] stop qualified certificate @@ -613,7 +661,7 @@ public class BKUConnector implements LocalConnector verify_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str); if (logger_.isDebugEnabled()) { - //logger_.debug(verify_request + "_request.xml : " + verify_req_str); + logger_.debug("verify_req_str.xml : " + verify_req_str); } return verify_req_str; @@ -630,12 +678,12 @@ public class BKUConnector implements LocalConnector * @throws SignatureException * F.e. */ - protected String sendRequest(String url, String request_string) throws SignatureException + protected Properties sendRequest(String url, String request_string) throws SignatureException { try { - String response_string = BKUPostConnection.doPostRequest(url, request_string); - return response_string; + Properties response_properties = BKUPostConnection.doPostRequest(url, request_string); + return response_properties; } catch (Exception e) { @@ -644,11 +692,14 @@ public class BKUConnector implements LocalConnector } } - public SignatureObject analyzeSignResponse(String response_string, + public SignatureObject analyzeSignResponse(Properties response_properties, String sigType) throws SignatureException { //String sign_request_filename = getSignRequestTemplateFileName(sigType); + // TODO hotfix + String response_string = response_properties.getProperty("response_string"); + SignatureObject sig_obj = new SignatureObject(); sig_obj.setRawSignatureResponse(response_string); try @@ -699,17 +750,19 @@ public class BKUConnector implements LocalConnector { if (logger_.isDebugEnabled()) { - //logger_.debug(sign_request_filename + "_response.xml : " + response_string); + logger_.debug("signature_response_string: " + response_string); } - parseCreateXMLResponse(response_string, sig_obj); + parseCreateXMLResponse(response_properties, sig_obj); } } sig_obj.setSigResponse(response_string); return sig_obj; } - public SignatureResponse analyzeVerifyResponse(String response_string) throws SignatureException + public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws SignatureException { + String response_string = response_properties.getProperty("response_string"); + if (!response_string.equals("")) { Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>"); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java index 773b248..1ddef5f 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java @@ -18,7 +18,11 @@ package at.knowcenter.wag.egov.egiz.sig.connectors; import java.io.IOException; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.NameValuePair; @@ -52,7 +56,7 @@ public abstract class BKUPostConnection * @throws HttpException * ErrorCode:320 */ - public static String doPostRequest(String url, String request) throws HttpException, IOException + public static Properties doPostRequest(String url, String request) throws HttpException, IOException { PostMethod post_method = new PostMethod(url); @@ -81,6 +85,23 @@ public abstract class BKUPostConnection int method_response = http_client.executeMethod(post_method); logger_.debug("method_response = " + method_response); + Properties response_properties = new Properties(); + + if (logger_.isDebugEnabled()) + { + Header[] response_headers = post_method.getResponseHeaders(); + logger_.debug("#" + response_headers.length + " headers in response:"); + for (int i = 0; i < response_headers.length; i++) + { + logger_.debug(" response_header[" + i + "]: name = " + response_headers[i].getName() + ", value = " + response_headers[i].getValue()); + } + } + + Header server_header = post_method.getResponseHeader("Server"); + logger_.debug("server_header: name = " + server_header.getName() + ", value = " + server_header.getValue()); + parseBKUVersion(server_header.getValue(), response_properties); + + byte[] response_body = post_method.getResponseBody(); String response_string = new String(response_body, "UTF-8"); @@ -89,7 +110,36 @@ public abstract class BKUPostConnection // response. // String response_string = post.getResponseBodyAsString(); - return response_string; + response_properties.setProperty("response_string", response_string); + + return response_properties; } + // TODO hotfix + public static void parseBKUVersion(String header_value, Properties properties) + { + Pattern pattern = Pattern.compile("^citizen-card-environment/(\\d+\\.\\d+) (.+)/(\\d+\\.\\d+\\.\\d+)$"); + Matcher m = pattern.matcher(header_value); + + m.matches(); + + logger_.debug("group count = " + m.groupCount()); + + for (int i = 0; i <= m.groupCount(); i++) + { + logger_.debug(" group[" + i + "] = " + m.group(i)); + } + + final String cceVersion = m.group(1); + final String productName = m.group(2); + final String productVersion = m.group(3); + + logger_.debug("cceVersion = " + cceVersion); + logger_.debug("productName = " + productName); + logger_.debug("productVersion = " + productVersion); + + properties.setProperty("cceVersion", cceVersion); + properties.setProperty("productName", productName); + properties.setProperty("productVersion", productVersion); + } } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/web/AsynchronousDataResponder.java b/src/main/java/at/knowcenter/wag/egov/egiz/web/AsynchronousDataResponder.java index 847bbcf..52846f5 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/web/AsynchronousDataResponder.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/web/AsynchronousDataResponder.java @@ -18,7 +18,9 @@ package at.knowcenter.wag.egov.egiz.web; import java.io.IOException; +import java.util.Enumeration; import java.util.List; +import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -34,6 +36,7 @@ import org.apache.log4j.Logger; import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger; import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.sig.connectors.BKUPostConnection; /** * Servlet that responds to the data post requests of the local service (e.g. @@ -143,7 +146,23 @@ public class AsynchronousDataResponder extends HttpServlet } - si.response_string[si.current_operation] = resp_string; //request.getParameter("XMLResponse"); + // TODO hotfix + if (logger_.isDebugEnabled()) + { + Enumeration header_names = request.getHeaderNames(); + while (header_names.hasMoreElements()) + { + String header_name = (String)header_names.nextElement(); + String header_value = request.getHeader(header_name); + logger_.debug("header: name = " + header_name + ", value = " +header_value); + } + } + String user_agent = request.getHeader("User-Agent"); + logger_.debug("User-Agent header = " + user_agent); + Properties response_properties = new Properties(); + BKUPostConnection.parseBKUVersion(user_agent, response_properties); + response_properties.setProperty("response_string", resp_string); + si.response_properties[si.current_operation] = response_properties; //request.getParameter("XMLResponse"); //logger_.debug("AsyncDataResponder: si.response_string[si.current_operation] = " + si.response_string[si.current_operation]); si.current_operation++; diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/web/AsynchronousRedirectResponder.java b/src/main/java/at/knowcenter/wag/egov/egiz/web/AsynchronousRedirectResponder.java index b79dd87..031b03c 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/web/AsynchronousRedirectResponder.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/web/AsynchronousRedirectResponder.java @@ -147,9 +147,9 @@ public class AsynchronousRedirectResponder extends HttpServlet { List results = new ArrayList(); - for (int i = 0; i < si.response_string.length; i++) + for (int i = 0; i < si.response_properties.length; i++) { - SignatureResponse sig_resp = local_conn.analyzeVerifyResponse(si.response_string[i]); + SignatureResponse sig_resp = local_conn.analyzeVerifyResponse(si.response_properties[i]); results.add(sig_resp); } @@ -176,7 +176,7 @@ public class AsynchronousRedirectResponder extends HttpServlet // has already been computed - don't recompute it. if (si.sign_result == null) { - si.iui.signed_signature_object = local_conn.analyzeSignResponse(si.response_string[0], si.type); + si.iui.signed_signature_object = local_conn.analyzeSignResponse(si.response_properties[0], si.type); PdfASID algorithm = FormFields.translateSignatureModeToPdfASID(si.mode); Signator signator = SignatorFactory.createSignator(algorithm); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/web/LocalRequestHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/web/LocalRequestHelper.java index 50bea41..95f72ef 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/web/LocalRequestHelper.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/web/LocalRequestHelper.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.Properties; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -82,8 +83,8 @@ public abstract class LocalRequestHelper si.requests = new LocalRequest[1]; si.requests[0] = new LocalRequest(local_conn.getSignURL(si.type), request_string); si.current_operation = 0; - si.response_string = new String[1]; - si.response_string[0] = null; + si.response_properties = new Properties[1]; + si.response_properties[0] = null; // SessionTable.put(si); request.getSession().setAttribute(SessionAttributes.ATTRIBUTE_SESSION_INFORMATION, si); @@ -113,7 +114,7 @@ public abstract class LocalRequestHelper HttpServletResponse response) throws SignatureException, NormalizeException, IOException, ConnectorFactoryException { si.requests = new LocalRequest[holders_to_verify.size()]; - si.response_string = new String[si.requests.length]; + si.response_properties = new Properties[si.requests.length]; si.current_operation = 0; si.finished = false; @@ -134,7 +135,7 @@ public abstract class LocalRequestHelper LocalRequest local_request = new LocalRequest(local_conn.getVerifyURL(holder.getSignatureObject().getSignationType()), request_string); si.requests[i] = local_request; - si.response_string[i] = null; + si.response_properties[i] = null; } // ByteArrayOutputStream baos = new ByteArrayOutputStream(); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/web/SessionInformation.java b/src/main/java/at/knowcenter/wag/egov/egiz/web/SessionInformation.java index f3c34d3..52a51a3 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/web/SessionInformation.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/web/SessionInformation.java @@ -19,6 +19,7 @@ package at.knowcenter.wag.egov.egiz.web; import java.io.Serializable; import java.util.List; +import java.util.Properties; import at.knowcenter.wag.egov.egiz.framework.SignResult; import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; @@ -91,7 +92,7 @@ public class SessionInformation implements Serializable /** * An array of response strings of the local requests. */ - public String[] response_string = null; + public Properties[] response_properties = null; /** * Tells, if the current local request has been finished. diff --git a/src/main/java/com/lowagie/text/pdf/PdfDictionary.java b/src/main/java/com/lowagie/text/pdf/PdfDictionary.java index f7310e4..acf84d5 100644 --- a/src/main/java/com/lowagie/text/pdf/PdfDictionary.java +++ b/src/main/java/com/lowagie/text/pdf/PdfDictionary.java @@ -105,11 +105,20 @@ public class PdfDictionary extends PdfObject { /** This is the hashmap that contains all the values and keys of the dictionary */ protected HashMap hashMap; + + // EGIZ various modifications /** * This list preserves the order of the elements. + * + *

+ * If an element to be added to the list already exists in the list, + * it sould not be added as the contents of this new element + * overwrites the contents of the old element in the hash map. + *

*/ protected List list; + // constructors /** @@ -175,8 +184,13 @@ public class PdfDictionary extends PdfObject { */ public void put(PdfName key, PdfObject value) { + if (!hashMap.containsKey(key)) + { + // If the key is new, add it to the ordered list. + // If not, it already has a position in the list. + list.add(key); + } hashMap.put(key, value); - list.add(key); } /** -- cgit v1.2.3